Inicjalizacja obiektów w kompozycji w c++

0

Witam,

Mam mniej więcej (w dużym uproszczeniu) taki kod :

class A 
{
public:
   A(std::string s) {text = s};
   ~A();
private:
   std::string text;
}


class B 
{
public:
   B();
   ~B()
private:   
    A x;
}

Jak mogę zainicjalizować zmienną x w klasie B ? Próbowałem w konstruktorze B wywołać x(std::string) - błąd, x {std::string} - błąd. Jedyne co mi przyszło do głowy i rzeczywiście działa to dodanie metody

 void A::set_val(std::string s) {text = s}

,ale zastanawiam się czy to jest poprawne(jedyne?) rozwiązanie? Wiem oczywiście że mogę tą zmienna zamienić na wskaźnik i zainicjować

 x = new A(std::string) 

ale staram się takiego rozwiązania uniknąć.

Prośba o pomoc.

4

Użyj listy inicjalizacyjnej https://ideone.com/Au7xLc

2

Ten Twoj kod nawet sie nie kompiluje...

#include <iostream>
#include <string>

using namespace std;

class A 
{
public:
   A(std::string s):text(s){};
   ~A();
private:
   std::string text;
};
 
 
class B 
{
public:
   B(): x (A(std::string("tutaj jakis Text"))){};
   ~B();
private:   
    A x;
};

int main()
{
    B foo();
} 

EDIT
no i oczywiscie nie powinienes uzywac golego new. Od tego masz smart pointery. Nie wiem co robisz, ale przeczuwam ze robisz cos dziwnego

0

Dzięki.

A jeśli nie chcę wpisać do A, całego str, tylko np jakiś jego kawałek lub np chcę zrobić tak:

class A {
public:   
    A(std::String s) {text = s}
private:   
    std::string text;}
class B{B(
public:    
    std::String s) {text = s}
private:    
    std::string text;}
class C{
  A x;
  B y;
  C(std::vecotr<std::string> v) : C(A(v[0])), C(B(v[1]))   { } 

// najchętniej bym zrobił tak 
for (... i < v.size() ... ) 
          switch (i) 
          { //wywołanie poszczególnych konstruktorów }
}
 

da się takie coś zrobić bez wskaźników?
Z tego co zauwazyłem to jeśli mam w definicji klasy np

 A x 

To wywołuję się konstruktor domyślny (który mogę zdefiniować i zerować zmienne)
a potem metodą

void A::set_val(std::string) 

sobie ustawiać te zmienne zgodnie z tym co mi jest potrzebne.

4

o nie nie nie, ja sie nie bede tak bawil z tym co napisales powyzej. Spedz troche czasu nad tym by to normalnie napisac
Dlaczego nikt nie odpowiada w moim wątku?

0

Zamiast void A::set_val(std::string); wywołaj po prostu konstruktor obiektu z parametrem std::string i masz to samo.
PS: Tego kodu w ogóle nie da się czytać. Nadal przepisujesz te same błędy.

0
#include <string>
#include <iostream>
#include <vector>

class A 
{

public:
	A(std::string s) { text = s };
	std::string get_text() { return text};

private:
	std::string text;

};

class B 
{

public:
	std::string s) { text = s };
	std::string get_text() { return text};

private:
   std::string text;

};
class C
{

public: 
	A x;
	B y;
	C(std::vecotr<std::string> v) : x(A(v[0])), y(B(v[1])) {}; //????

};

int main()
{

std::vector<std::string> vector {"123","abc"};

C test(vector);
std::cout << test.x.get_text() << std::endl;
std::cout << test.y.get_text() << std::ednl;

std::cin.get();
return 0;
} 

Mam nadzieję że teraz jest czytelne. Czy ktoś może mi podpowiedzieć jak mam prawidłowo to zainicjalizować zmienne x,y (i potencjalnie więcej) w takiej sytuacji.

2
C(const vector<string>& v) : x(v[0]), y(v[1]) {}
0

Teraz mam taki kod (sprawdziłem kompiluje się) :

#include <iostream>

class anyother
{
public:
	anyother() : z(0) {};
	anyother(int a) : z(a) {};
	~anyother(){};
	int get_z() { return z; };
private:
	int z;
};

class base
{
public:
	virtual ~base(){};
	int get_t() { return t.get_z(); };
protected:
	anyother t;
};

class next : public base
{
public:
	next(int a) 
	{
		t = { a };
	};
	~next() {};
};

int main()
{
	next n(3);
	std::cout << n.get_t() << std::endl;
	std::cin.get();
	return 0;
}

Czy jest jakiś sposób żeby zainicjalizować obiek klasy next za pomocą listy inicjalizacyjnej (podana wcześniej konstrukcja niestety nie działa), lub może jest inna konstrukcja która pozwoli od razu zainicjalizować zmienną odpowiednią wartością? W tym zapisie najpier jest wywoływany konstruktor domyślny ( tak pokazał mi debbuger). W przypadku próby inicjalizacji listą w postaci:

 next(int a) : t(a) {}; 

Kompilator podkreśla mi to z komunikatem :

"t" is not a nonstatic data member or base class of class "next"

error C2614: 'next' : illegal member initialization: 't' is not a base or member

0

Musisz stworzyć konstruktor w klasie bazowej, który przyjmie inta i zainicjalizuje sobie nim anyother::t. Potem w liście inicjalizacyjnej klasy pochodnej wywołujesz konstruktor klasy bazowej.

#include <iostream>
 
class anyother
{
public:
    anyother() : z(0) {};
    anyother(int a) : z(a) {};
    ~anyother(){};
    int get_z() { return z; };
private:
    int z;
};
 
class base
{
public:
	base( int a ) :
		t( a )
	{}
		
    virtual ~base(){};
    int get_t() { return t.get_z(); };
protected:
    anyother t;
};
 
class next : public base
{
public:
    next(int a) :
    	base( a )
    {};
    
    ~next() {};
};
 
int main()
{
    next n(3);
    std::cout << n.get_t() << std::endl;
    std::cin.get();
    return 0;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1