본문 바로가기

Coding Note

[C++] 상속과 다형성

포멧한다고 정리하다가 예전에 써둔거 발견


상속을하면? 클래스들 간의 관계가 명확해진다. 또한 상속, 다중상속을 통해 코드중복 최소화할 수 있다.
상속의 유형(유형이라고 해야하나..)?
public : Base클래스의 멤버의 접근지정자를 그대로 받아옴
protected : Base클래스의 접근지정자를 protected화 함
private : Base클래스의 멤버 점근지정자를 private화 함
상속유형 사용 이유, 두번째, 세번째 상속으로 이어져나갈 때, 부모의 멤버를 어떻게 대하도록 할 지 결정하기 위함

#상속의 관계
IS - A,  HAS - A관계

학생is a 사람 (사람이 베이스 클래스) :: 관계 명확성에 중점
대부분의 상속관계가 이 이유때문에 작성된다.
관계를 명확하게 해주기 때문에 상속이 아니라면 표현하기 힘들다.
학생 has a 학생증 (학생증이 베이스 클래스) :: 코드 중복 방지에 중점(개인적인 생각)
has a 관계는 클래스 내 멤버로써 나타내는게 더 명확하기 때문에 잘 사용되지 않음
(has a 관계를 상속을 통해 나타내면 두 클래스간 결합도가 높아져서 꼭 필요한 경우가 아니면 피하는게 좋음)

#상속과 overriding

overriding이란? : 부모클래스의 함수를 자식클래스에서 재정의 하는것(오버로딩과 다름)
부모클래스의 함수를 (같은 동일한 리턴타입, 함수명, 매개변수) 재정의
부모의 기능을 자식이, 유사하지만 조금 다른 형태로 기능하려고 할 때 오버라이딩함
(비슷한 기능을 다른 매개변수를 위해 오버로딩하는것과 개념적으로 비슷한 부분이 있다.
하지만 전혀 다름!!  주의!!!)

//--------------overriding example-------------------//
class Parent
{
public:
Parent(){}
void actingSomething(){ cout<<"부모의 행동"<<endl; }
};

class Son : public Parent
{
public:
Son(){}
void actingSomething(){cout<<"부모를 따라하지만 조금 어설픈 행동"<<endl;}
//부모의 같은이름의 메서드를 오버라이딩 하고있다.
};

void main()
{
Parent p();
Son s();
p.actingSomething(); //부모의 메서드 호출
s.actingSomething(); //자식의 오버라이딩 된 메서드 호출
}
//-----------------------------------------------//

#다형성
상속된 객체에 대한 포인터
@부모의 포인터로 자식을 가리킬 수 있다.
@부모의 레퍼런스는 자식을 가리킬 수 있다.

가능한 이유는, IS - A 관계에서 생각해보면 간단하다.
ex)사람은 동물이다 (부모클래스가 동물)
    클래스 포인터는 클래스의 주소값을 가진다.(가리킬 수 있다)
     사람클래스의 객체는 동물클래스의 객체이다.
     즉, 사람클래스의 객체는 사람클래스의 객체이자 동물클래스의 객체이다.
     따라서 동물은 사람을 가리킬 수 있다.

//-----------------다형성 예제--------------------//
class Base
{
public:
Base(){}
void show(){cout<<"Base"<<endl;}
};

class Derived : public Base
{
public:
Derived(){}
void show(){cout<<"Derived"<<endl;}
};

void main()
{
Derived* d = new Derived(); //당연히 가능하죠
Base* b = new Base(); //이것도 당연
Base* b2 = d; //아닛!  이런게 가능하다니!!!
d->show(); //"Derived" 출력
b->show(); //"Base" 출력
b2->show(); //"Derived" 출력
}
//----------------------------------------------//

#상속과 다형성 및 링크드리스트에의 활용
#include<iostream>
using namespace std;

class A
{
private:
int data;
public:
A()
{data = 0;}
A(int a):data(a){}
A(A* a){
this->data = a->data;
}
virtual void Func(){cout<<"A's Function"<<endl;}
};

class B : public A
{
public:
B():A(){}
B(int a):A(a){}
void Func(){cout<<"B's Function"<<endl;}
};

class C : public A
{
public:
C():A(){}
C(int a):A(a){}
void Func(){cout<<"C's Function"<<endl;}
};

class node
{
public:
node* next;
node* prev;
A* dat;
node(){next = NULL; prev = NULL; dat = NULL;}
node(A* a){next = NULL; prev = NULL; dat = NULL;  dat = a; }
};

class List
{
private:
node* start;
node* now;
public:
List(A* firstA){ 
start = new node();
node* newNode = new node(firstA);
start->next = newNode;
now = NULL;
}

void add(A* newclass)
{
now = start;
node* newnode = new node(newclass);

while(now->next != NULL)
{
now = now->next;
}
now->next = newnode;
newnode->prev = now;
newnode->dat = newclass;
}

void showFunc()
{
now = start;
while( now->next != NULL)
{
now = now->next;
now->dat->Func();
}
}
};

void main()
{
List ls(new A());
ls.add(new B());
ls.add(new C());

ls.showFunc();
}

'Coding Note' 카테고리의 다른 글

[WPF] 첫번째 프로그램  (0) 2012.01.16
[WPF] WPF 시작하기  (1) 2012.01.16
[OpenCL] AMD OpenCL configurate the interface at visual studio 2008  (0) 2011.12.02
[OpenCL] About  (0) 2011.11.22
[winAPI] API 환경변수 가져오기  (0) 2011.11.08