• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Dziedziczenie prywatne szablonu

0 głosów
976 wizyt
pytanie zadane 9 września 2017 w C i C++ przez B0nkers Początkujący (310 p.)

Witam,

Mam problem z zadaniem 2 z rozdziału 14, książki S. Prata "Język C++. Szkoła Programowania" .
Chodzi o dziedziczenie prywatne szablonu klasy.

Oto plik nagłówkowy i poniżej kod programu głównego.

#ifndef WINEC_H_
#define WINEC_H_
#include <iostream>
#include <valarray>
#include <string>
#include "stdafx.h"

template <class T1, class T2>
class Pair
{
protected:
	T1 Year;
	T2 Bottles;
public:
	T1 & first();
	T2 & second();
	T1 first() const 
	{
		return Year; 
	}
	T2 second() const
	{ 
		return Bottles; 
	}
	Pair(const T1 & aval, const T2 & bval) 
		: Year(aval), Bottles(bval) 
	{
	}
	Pair() {}
};

template <class T1, class T2>
T1 & Pair<T1, T2>::first()
{
	return Year;
}
template<class T1, class T2>
T2 & Pair<T1, T2>::second()
{
	return Bottles;
}

template <class T1, class T2>
class Wine : private Pair<T1, T2>
{
private:
	typedef std::valarray<int> ArrayInt;
	typedef Pair<ArrayInt, ArrayInt> PairArray;
	//PairArray <Pair::Year, Pair::Bottles>;
	std::string label;
	int count;
	//PairArray Amount;
public:

	template <class Pair>
	Wine()
		: PairArray()
	{
	}
	//inicjalizuje składową label parametrem l, liczbę lat parametrem y,
	//roczniki parametrem yr[], składową bottles parametrem bot[]

	//template <class Pair>
	Wine(const char * l, int y, const int yr[], const int bot[])
		: label(l), count(y), PairArray(ArrayInt(y),ArrayInt(y))
	{
		for (int i = 0; i < count; i++)
		{
			PairArray::first()[i] = yr[i];
			PairArray::second()[i] = bot[i];
		}
	}
	//inicjalizuje składową label parametrem l, liczbę lat parametrem y,
	//tworzy tablicę obiektów o długości y

	//template <class Pair>
	Wine(const char * l, int y)
		: label(l), count(y), PairArray(ArrayInt(y), ArrayInt(y))
	{
	}

	~Wine() {};
	//metody
	void GetBottles()
	{
		using std::cout;
		using std::cin;
		
		cout << "Podaj dane o winie \"" << label << "\" dla " << count << " rocznikow\n";
		for (int i = 0; i < count; i++)
		{
			cout << "Podaj rocznik: ";
			cin >> PairArray::first()[i];
			cout << "Podaj ilosc butelek: ";
			cin >> PairArray::second()[i];
		}
	}

	const std::string & Label() const
	{
		return label;
	}

	void Show() const
	{
		std::cout << "Wino \"" << label << "\"\n";
		std::cout.width(6);
		std::cout << "Rocznik   Butelki\n";
		for (int i = 0; i < count; i++)
		{
			std::cout.width(6);
			std::cout << PairArray::first()[i];
			std::cout.width(7);
			std::cout << PairArray::second()[i];
			std::cout << std::endl;
		}
	}

	int sum() const
	{
		int total = 0;
		for (int i = 0; i < count; i++)
			total += PairArray::second()[i];

		return total;
	}
};

#include "stdafx.h"
#include "winec02.h"

int main()
{
	using std::cin;
	using std::cout;
	using std::endl;

	cout << "Podaj nazwe wina: ";
	char lab[50];
	cin.getline(lab, 50);
	cout << "Podaj liczbe rocznikow: ";
	int yrs;
	cin >> yrs;

	Wine holding(lab, yrs);	//zapisuje nazwę, liczbę roczników i przekazuje informację o
							//tej liczbie do tablicy
	holding.GetBottles();	//pobiera dane o roczniku i liczbie butelek
	holding.Show();			//wyświetla zawartość obiektu

	const int YRS = 3;
	int y[YRS] = { 1993, 1995, 1998 };
	int b[YRS] = { 48, 60, 72 };
	//tworzy nowy obiekt, inicjalizuje za pomocą danych w tablicach y oraz b
	Wine more("Gushing Grape Red", YRS, y, b);
	//more.Show();
	//cout << "Laczna liczba butelek wina " << more.Label()	//używa metody Label()
	//	<< ": " << more.sum() << endl;	//używa metody sum()
	cout << "Koniec\n";


	system("PAUSE");
	return 0;
}

 

Proszę o pomoc w znalezieniu błędów smiley

 

komentarz 9 września 2017 przez criss Mędrzec (172,570 p.)
A na czym polega problem? (dlaczego trzeba o to pytać)
komentarz 9 września 2017 przez B0nkers Początkujący (310 p.)
przeniesione 10 września 2017 przez draghan
Polega na tym że nie wiem czy to do końca dobrze zrobiłem, kompilator wyświetla błędy w konkretyzacji
komentarz 10 września 2017 przez criss Mędrzec (172,570 p.)
A nie zamierzasz może podzielić się z nami tymi błędami? Ja nie rozumiem. Czy to nie jest oczywiste, że znajomość błędów pomaga w szukaniu problemów?

PS: następnym razem pisz w komentarzach, zamiast tworzyć nową odpowiedź

2 odpowiedzi

+1 głos
odpowiedź 10 września 2017 przez j23 Mędrzec (195,240 p.)
wybrane 10 września 2017 przez B0nkers
 
Najlepsza
Wine holding(lab, yrs);
...

Wine more("Gushing Grape Red", YRS, y, b);

Wine jest szablonem, a Ty tworzysz instancje tej klasy, jakby była zwykłą klasą. Podaj parametry szablonu przy tworzeniu:

using vaint_t = std::valarray<int>;

Wine<vaint_t, vaint_t> holding(lab, yrs);
 ... 

Wine<vaint_t, vaint_t> more("Gushing Grape Red", YRS, y, b);

albo dziedzicz tak:

using vaint_t = std::valarray<int>;

class Wine : private Pair<vaint_t, vaint_t> { ... }

 

komentarz 10 września 2017 przez B0nkers Początkujący (310 p.)

No dobra ale jak dam nic i usunę <vaint_t, vaint_t> przy Wine, to wtedy wyskakują błędy typu:

"more" niezadeklarowany identyfikator

 

komentarz 10 września 2017 przez B0nkers Początkujący (310 p.)
Dobra już wpadłem na to, wystarczyło tylko zasięg w metodach i konstruktorach dopisać
komentarz 10 września 2017 przez B0nkers Początkujący (310 p.)

A w pierwszej wersji to  template <class T1, class T2> musi być przed klasą?

komentarz 10 września 2017 przez j23 Mędrzec (195,240 p.)

Tu masz kod, który powinien skompilować się bez błędu/warninga:

template <class T1, class T2>
class Pair
{
protected:
    T1 Year;
    T2 Bottles;
public:
    T1 & first()  { return Year; }
    T2 & second() { return Bottles; }
    T1 first() const { return Year; }
    T2 second() const { return Bottles; }
    
	Pair(const T1 & aval, const T2 & bval) 
        : Year(aval), Bottles(bval) 
    {}

	Pair(T1 && aval, T2 && bval) 
        : Year(aval), Bottles(bval) 
    {}
	
    Pair() {}
};
 
 
using vaint_t = std::valarray<int>; 


class Wine : private Pair<vaint_t, vaint_t>
{
private:
    std::string label;
    int count;

public:

    Wine()
        : count(0)
    { }

    Wine(const char * l, int y, const int yr[], const int bot[])
        : Pair<vaint_t, vaint_t>(vaint_t(yr, y), vaint_t(bot, y)),
		label(l), 
		count(y)
		
    { }

    Wine(const char * l, int y)
        : Pair(vaint_t(y), vaint_t(y)),
		label(l), 
		count(y)		
    { }
 
    ~Wine() {};
    
    void GetBottles()
    {
        using std::cout;
        using std::cin;
         
        cout << "Podaj dane o winie \"" << label << "\" dla " << count << " rocznikow\n";
        for (int i = 0; i < count; i++)
        {
            cout << "Podaj rocznik: ";
            cin >> first()[i];
            cout << "Podaj ilosc butelek: ";
            cin >> second()[i];
        }
    }
 
    const std::string & Label() const
    {
        return label;
    }
 
    void Show() const
    {
        std::cout << "Wino \"" << label << "\"\n";
        std::cout.width(6);
        std::cout << "Rocznik   Butelki\n";
        for (int i = 0; i < count; i++)
        {
            std::cout.width(6);
            std::cout << first()[i];
            std::cout.width(7);
            std::cout << second()[i];
            std::cout << std::endl;
        }
    }
 
    int sum() const
    {
        int total = 0;
        for (int i = 0; i < count; i++)
            total += second()[i];
 
        return total;
    }
};

 

// przykładowo
const int YRS = 3;
int y[YRS] = { 1993, 1995, 1998 };
int b[YRS] = { 48, 60, 72 };

Wine more("Gushing Grape Red", YRS, y, b);

 

komentarz 10 września 2017 przez B0nkers Początkujący (310 p.)

Ok czyli z tego co widzę to zapomniałem tylko o jednej rzeczy,bo składowe Pair są chronione a nie prywatne i niepotrzebnie ten operator zasięgu wstawiałem w metodach smiley.  Wielkie dzięki! 

0 głosów
odpowiedź 10 września 2017 przez criss Mędrzec (172,570 p.)

Tutaj widzę jeden problem:

template <class T1, class T2>
class Wine : private Pair<T1, T2>
{
private:
    typedef std::valarray<int> ArrayInt;
    typedef Pair<ArrayInt, ArrayInt> PairArray;
    std::string label;
    int count;
public:
 
    template <class Pair>
    Wine()
        : PairArray()
    {
    }
// ...

Dziedziczysz z Pair<T1, T2> (T1 i T2 to parametry szablonu), ale konstruktor zawsze chce wołać konstruktor Pair<ArrayInt, ArrayInt>. Z listy inicjalizacyjnej możesz wołać tylko swój konstruktor, albo konstruktor klasy bazowej. Podobnych odwołań do PairArray (alias dla Pair<ArrayInt, ArrayInt>) jest w kodzie więcej i z tego na pewno wynikają problemy. 

Dodatkowo masz zszablonowany konstruktor, ale nigdzie z tego nie korzystasz.

Na razie tyle byłem w stanie znaleźć. Jeśli to nie rozwiązuje problemu, to pokaż treści błędów (w zasadzie mimo wszystko miło by było jak byś to zrobił).

PS: nie musisz wołać metod klasy bazowej w ten sposób jak teraz - możesz normalnie jak własną metode. Tak jak teraz (jawnie operatorem zasięgu mówiąc do kogo metoda należy) byłoby konieczne gdyby twoja klasa dziedzicząca definiowała takie same metody, a ty byś chciał zawołać tą z klasy bazowej.

komentarz 10 września 2017 przez B0nkers Początkujący (310 p.)
Czyli że w liście inicjalizacyjnej zamiast odwoływać się do PairArray, mam się odwołać do Pair?
komentarz 10 września 2017 przez criss Mędrzec (172,570 p.)
Do Pair<T1, T2>. Samo Pair to tylko szablon i nie jesteś w stanie się do niego odwołać.

Podobne pytania

+1 głos
0 odpowiedzi 408 wizyt
pytanie zadane 14 czerwca 2017 w Bezpieczeństwo, hacking przez RAD Obywatel (1,810 p.)
+1 głos
1 odpowiedź 3,775 wizyt
0 głosów
3 odpowiedzi 1,398 wizyt

93,426 zapytań

142,421 odpowiedzi

322,647 komentarzy

62,787 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

VMware Cloud PRO - przenieś swoją infrastrukturę IT do chmury
...