자식 클래스의 포인터를 부모클래스의 포인터로 바꾼후 다시 자식클래스포인터로 변경하기.

auto와 dynamic_cast를 사용한다.

dynamic_cast는 casting에 실패하면 nullptr을 반환한다.

static_cast도 사용가능하다. static_cast는 할 수 있는한 최대한 변환시킨다.
안되야 될것도 되는 경우가 생긴다. 하지만 사용할 만한 가치는 있다.
static_cast는 nullptr을 반환하지 않는다.

 

#include <iostream>
#include <string>

using namespace std;

class Base
{
public:
	int m_i = 0;
	virtual void print()
	{
		cout << "I'm Base" << endl;
	}

};

class Derived1 : public Base
{
public:
	int m_d = 0;
	virtual void print() override
	{
		cout << "I'm Derived1" << endl;
	}

};

class Derived2 : public Base
{
public:
	int m_d = 0;
	string m_s = "123";
	virtual void print() override
	{
		cout << "I'm Derived2" << endl;
	}

};
int main()
{

	Derived2 d2;
	Base *b = &d2;
	b->print();

	auto *base_to_d2 = dynamic_cast<Derived2*>(b);

	cout << base_to_d2->m_s << endl;


	return 0;
}

상속할때 보통 부모클래스보다는 자식클래스가 정보를 많이 가지고 있다.
이유 : 추가 함수,추가 변수,오버라이딩 등등

작은 부모의 객체에 큰 자식클래스를 대입한다면 다형성이 사라진다.

부모객체로 인식한다고 생각하면된다.

 

즉, 자식에 추가된 데이터들이 사라진다.


reference_wapper를 사용하거 포인터를 사용하면 객체잘림을 막을 수 있다.

 

당연, 포인터를 생각해보면 주소값을 대입하는거니 데이터는 그대로 남아있겠지?

 

#include <iostream>
#include <vector>

using namespace std;

class Base
{
public:
	int m_i = 0;
	virtual void print() 
	{
		cout << "I'm Base" << endl;
	}

};

class Der : public Base
{
public:
	int m_d = 0;
	virtual void print() override 
	{
		cout << "I'm Der" << endl;
	}

};
int main()
{
	Der d;
	Base b = d;
	b.print();
	
	//reference_wrapper를 사용하거나 *포인터 사용이가능하다.
	vector<reference_wrapper<Base>> my_vec;
	my_vec.push_back(b);
	my_vec.push_back(d);

	//reference_wrapper는 ref를 받아오기위해 get()을 사용한다.
	for (auto & a : my_vec)
		a.get().print();

	vector<Base*> my_vec2;
	my_vec2.push_back(&b);
	my_vec2.push_back(&d);

	for (auto & a : my_vec2)
		a->print();
	return 0;
}

다이아몬드 상속문제.

해결하기위해 가상 기본 클래스를 사용한다.
숫자는 class :는 상속을 나타낸다.
아래처럼 상속하면 다이아몬드 구조로 될거 같지만
1class가 두번 생성된다.
1
2 :(상속) 1 , 3 :(상속) 1
4 :(상속) 2,3

상속할때 상속하는 코드에 virtual을 쓰면 한번만 생성된다.
맨 마지막 자식 테이블에서 1class 생성자를 정의해준다.

 

#include <iostream>

using namespace std;
class PowerDevice
{

public:
	int m_power;
	PowerDevice(int power){
		cout << "PowerDevice : " << power << endl;
	}

};

class Scanner : virtual public PowerDevice
{
public:
	Scanner(int scan, int power)
		:PowerDevice(power) {
		cout << "Scanner : " << scan << endl;
	}
};

class Printer : virtual public PowerDevice
{
public:
	Printer(int prin, int power)
		:PowerDevice(power) {
		cout << "Printer : " << prin << endl;
	}
};

class Copier : public Scanner, public Printer
{
public:
	Copier(int scan, int prin, int power)
		:Scanner(scan, power), Printer(prin, power) ,PowerDevice(power){}
};
int main()
{
	Copier c(1, 2, 3);
	//주소값이 다르다.
	cout << &c.Scanner::PowerDevice::m_power << endl;
	cout << &c.Printer::PowerDevice::m_power << endl;
	return 0;
}

+ Recent posts