- private, protected, public 상속
 
class TestClass
{
private:
	void privateDo();
protected:
	void protectedDo();
public:
	void publicDo();
};
class InheritencePrivate : private TestClass {};
// private보다 넓은 공유 범위를 가지는 것들을 private로 전환하여 상속
class InheritenceProtected : protected TestClass {};
// protected보다 넓은 공유 범위를 가지는 것들을 protected로 전환하여 상속
class InheritencePublic : public TestClass {};
// 그대로 상속
void main()
{
	InheritencePrivate a;
	InheritenceProtected b;
	InheritencePublic c;
	a.privateDo();
	a.protectedDo();
	a.publicDo();
	// 모두 컴파일 에러
	b.privateDo();
	b.protectedDo();
	b.publicDo();
	// 모두 컴파일 에러
	c.privateDo();
	c.protectedDo();
	c.publicDo();
	// publicDo 제외 컴파일 에러
}
#include <iostream>
class TestClass
{
private:
	void privateDo();
protected:
	void protectedDo();
public:
	virtual void publicDo();
	virtual void publicDo(int num);
	void publicDo_2();
};
class Inheritence : public TestClass
{
public:
	void publicDo();
	void publicDo(int num);
	void publicDo_2();
};
void main()
{
	Inheritence * inst = new Inheritence();
	TestClass * tcInst = new TestClass();
	inst->publicDo();
	inst->publicDo_2();
	TestClass * convertInst = new TestClass();
	convertInst = (TestClass *) inst;
	convertInst->publicDo();
	convertInst->publicDo_2();
	
	// 다형성은 포인터 변수의 자료형을 기준으로 하며, virtual이 선언되어 있지 않으면 적용되지 않음.
	/* output
	Inheritence publicDo
	Inheritence publicDo_2
	Inheritence publicDo
	TestClass publicDo_2
	*/
}
void TestClass::publicDo()
{
	std::cout << "TestClass publicDo" << std::endl;
}
void TestClass::publicDo(int num)
{
	std::cout << "TestClass overloading publicDo" << std::endl;
}
void Inheritence::publicDo()
{
	std::cout << "Inheritence publicDo" << std::endl;
}
void Inheritence::publicDo(int num)
{
	std::cout << "Inheritence overloading publicDo" << std::endl;
}
void TestClass::publicDo_2()
{
	std::cout << "TestClass publicDo_2" << std::endl;
}
void Inheritence::publicDo_2()
{
	std::cout << "Inheritence publicDo_2" << std::endl;
}
// 업 캐스팅이란 파생 클래스의 객체를 기본 클래스의 포인터로 가리키는 것을 말한다.
// 다운 캐스팅이란 기본 클래스의 객체를 파생 클래스의 객체로 가리키는 것을 말한다.
class Point
{
private:
	int x, y;
	
public:
	void set(int x, int y);
	void showPoint();
};
class ColorPoint : public Point
{
private:
	string color;
public:
	void setColor(string color);
	void showColorPoint();
};
void main(void)
{
	ColorPoint cp;
	ColorPoint * pCp = &cp;
	Point * pP = pCp;							// 업 캐스팅
	Point * newPp = new Point();
	ColorPoint * newPcP = (ColorPoint *) newPp;
        // 다운 캐스팅. 명시적으로만 가능하다.
	newPcP->showColorPoint();		
	// 컴파일 오류가 발생하지 않는다. 주의할 것.
}
class TestClass
{
private:
	void privateDo();
protected:
	void protectedDo();
public:
	virtual void publicDo() = 0;		// 이 메서드는 순수 가상 함수로, 자식 클래스에서 반드시 재정의
	virtual void publicDo(int num);
	void publicDo_2();
};
// 순수 가상 함수가 하나 이상있으면 추상 클래스 취급되어 인스턴스 생성 불가능
class TestClass
{
private:
	char * cString;
public:
	TestClass()
	{
		cString = new char[20];
	}
	virtual ~TestClass()
	{
		delete[] cString;
	}
};
class Inheritence : public TestClass
{
private:
	int * intArr;
public:
	Inheritence()
	{
		intArr = new int[20];
	}
	~Inheritence()
	{
		delete[] intArr;
	}
};
// Inheritence에서 소멸자가 호출되지 않아 메모리가 누수될 가능성이 있기 때문에 가상 소멸자 사용
- 다중 상속과 virtual base class
 
class SuperClass
{
public:
	virtual void DoSomething();
};
class HalfSuperClass_1 : public virtual SuperClass
{
};
class HalfSuperClass_2 : public virtual SuperClass
{
};
class ChildClass : public HalfSuperClass_1, public HalfSuperClass_2
{
};
void main(void)
{
	ChildClass inst;
	inst.DoSomething();
}
// SuperClass에 있는 함수를 사용하려 할 때, 모호성을 제거하기 위해서 상속 시 virtual 키워드를 통해 상속한다.
// 컴파일러에게 파생 클래스의 객체가 생성될 때 기본 클래스의 멤버 공간을 오직 한 번만 할당하고, 이미 할당되어 있다면 그 공간을
// 공유하도록 함으로써, 가상 기본 클래스의 멤버 공간은 오직 한 번만 할당하는 것을 의미
// 다만, 이것 전에 다중 상속은 왠만해서 쓰지말자.
- 상속/오버라이드 방지 및 override 키워드
 
class TestClass final // 이럴 경우 상속 불가능
{
private:
	void privateDo();
protected:
	void protectedDo();
public:
	virtual void publicDo() final; // 이럴 경우 오버라이딩 불가능
	virtual void publicDo(int num);
	void publicDo_2();
};
class Inheritence : public TestClass
{
public:
	void publicDo();
	void publicDo(int num) override;
        // override 한 것을 명시적으로 표현함 (매개 변수 등에서 에러가 날 경우 방지할 수 있음)
	void publicDo_2();
};
class TestClass
{
public:
	TestClass();
	TestClass(int num);
};
class Inheritence : public TestClass
{
public:
	using TestClass::TestClass;
	/* 생성되는 것들
	Inheritence(int num) : TestClass(num) {};
	Inheritence() : TestClass() {};
	*/
};
void main()
{
	Inheritence c(10);
}