'C++프로그래밍/C++'에 해당되는 글 15건

#include <iostream>

#define MAX_QUEUE_SIZE 100

using std::cout;
using std::endl;
using std::cin;

class queue{
 int rear;
 int front;
 int queues[MAX_QUEUE_SIZE];
public:
 void init();
 void addq(int item);
 void deleteq();
 void show();
};
void queue::init()
{
 rear=front=0;
 queues[rear]=0;
 queues[front]=0;
}
void queue::addq(int item)
{
 rear=(rear+1) % MAX_QUEUE_SIZE;
 if(front == rear){
  cout<<"queue is full";
  }
 queues[rear]=item;
}
void queue::deleteq()
{
 if(front == rear){
  cout<<"queue is empty";
 }
 front=(front+1) % MAX_QUEUE_SIZE;
 return;// queues[front];
}
void queue::show()
{
 cout<<"front : "<<queues[front]<<"  "<<"rear : "<<queues[rear]<<endl;
}

int main(void)
{
 queue q1;
 q1.init();
 q1.show();

 q1.addq(10);
 q1.show();
 q1.addq(20);
 q1.show();
 q1.addq(30);
 q1.show();
 q1.addq(40);
 q1.show();
 q1.addq(50);
 q1.show();
 return 0;
}


블로그 이미지

百見 이 不如一打 요 , 百打 가 不如一作 이다.

,

13장정리

C++프로그래밍/C++ 2007. 7. 29. 14:21

1. 기존의 예외처리 방식

int main(){
 int a,b;
 cout<<"두개의 숫자입력 :";
 cin>>a>>b;

 if(b==0) //예외상황이 발생을 한다면
  cout<<"오류"<<endl;
 else{
  cout<<"a/b의 몫 :"<<a/b<<endl;
  cout<<"a/g의 나머지 : "<<a%b<<endl;
 }
 
 return 0;
}


if문은 예외 처리 이외의 기능도 하기때문에 다른사람이 그 소스코드를 봤을때 분석하기가 힘들다.

2. C++ 예외처리 메커니즘
기본적인 예외 처리 메커니즘 (try,catch,throw)

try{
   //예외 발생 예상 지역
}
catch(처리되어야 할 예외의 종류){
   //예외를 처리하는 코드가 존재할 위치
}


catch블록은 항상 try 블록의 바로 뒤에 등장한다 try와 catch는 한문장으로 간주한다.
try블록 내에서 발생하는 예외 상황은 catch블록에 의해서 처리된다.

int main(){
 int a,b;
 cout<<"두개의 숫자입력:";
 cin>>a>>b;

 try{
  if(b==0)
   throw b;  // b를 가리켜 예외라고 한다
  cout<<"a/b의 몫 : "<<a/b<<endl;
  cout<<"a/b의 나머지 : "<<a%b<<endl;
 }
 catch(int exception){
  cout<<exception<<"입력."<<endl;
  cout<<"입력오류"<<endl;
 }


try블록에서 발생한 예외의 상황은 throw에 의해서 catch로 전달되어 처리된다.
전달이 되는 예의와 받아주는 변수의 자료형이 일치를 해야한다.

예외가 발생되면 try블록의 나머지 블록은 실행되지 않는다. 아래문장들은 실행이 되지 않고 catch의 블록 문장이 실행된후 종료된다.

3. 스택풀기
사용자 삽입 이미지

예외가 발생하였는데 그 예외를 처리해줄 try~catch문이 없다면 발생한 예외는 호출발생시킨 함수를 호출한 영역으로 전달된다.
----------------------------------------------------------------------------------------
사용자 삽입 이미지

위의 예제와 같은 예외의 처리방식은 스택에서 메모리가 해제 되는 방식과 같다하여 스택풀기
라고도 한다.
별..-_-;;

예외가 처리가 되지 않으면 stdlib 헤더 파일에 있는 abort함수가 호출되면서 프로그램은 종료된다

catch블록에 예외가 전달되는 방식
사용자 삽입 이미지


블로그 이미지

百見 이 不如一打 요 , 百打 가 不如一作 이다.

,

12장정리

C++프로그래밍/C++ 2007. 7. 28. 11:36
1. 템플릿(template)에 대한 이해
int add(int a, intb)
{
   return a+b;
}
위의 add함수를 템플릿으로 구현하면 다음과 같다
template <typename T> //typename T에 대해 다음에  정의하는
T add(T a, T b)                 //대상을 템플릿으로 선언한다.
{
   return a+b;
}


template <typename T> == template <class T>
같은 의미이다 그러나 과거에 주로 사용되던 방식이 후자이다.
T는 자료형을 결정짓지 않겠다는 의미로 사용된것이다.

#include <iostream>

using std::cout;
using std::endl;

template <typename T>
T Add(T a, T b){
 return a+b;
}

int main(){
 cout<<Add(10,20)<<endl;
 cout<<Add(1.1,2.2)<<endl;

 return 0;
}


첫번째 Add함수 호출시에는 전달되는 인자가 int형 데이터이다 .이런경우 템플릿으로 정의되어
있는 Add함수의 T는 int로 인식이 된다.
두번째 Add함수 호출시에는 double형이기때문에 double로 인식된다.

템플릿으로 정의된 함수의 자료형이 결정되는 시점은 인자가 전달되는 순간이다.

2. 함수 템플릿
둘이상의 타입에 대해 템플릿화 하기
template <typename T1,typename T2>  //함수 템플릿 정의
T1과T2라는 이름에 대해 다음에 정의하는 대상을 템플릿으로 선언한다. 라는 의미.

함수템플릿의 특수화
template <> //함수 템플릿의 특수화 선언

template <typename T>
int sizeOf(T a){
 return sizeof(a);
}
template<>
int sizeOf(char* a){
 return strlen(a);
}

int main(){
 int i=10;
 double e=7.7;
 char* str="Good Morning";

 cout<<sizeOf(i)<<endl;
 cout<<sizeOf(e)<<endl;
 cout<<sizeOf(str)<<endl;
 return 0;
}


템플릿의 특수화 선언이다. 보통 한줄로 붙여서쓴다
template<> int sizeOf(char* a)
template<> int sizeOf<>(char* a)
template<> int sizeOf<char*>(char* a)
모두 같은의미 이므로 다 알아둘것.

클래스 템플릿
template <typename T>
class Data{
 T data;
public:
 Data(T d){
  data=d;
 }
 void SetData(T d){
  data=d;
 }
 T GetData(){
  return data;
 }
};


template 다음에 정의하는 대상을 T라는 이름에 대해서 템플릿화 하겠다.
클래스 템플릿의 개체를 생성할때는
Data dd(10); 이 아니라 Data<int> dd(10); 으로 해주어야 한다.
객체는 1)메모리공간 할당 2)생성자 호출의 순으로 생성이 되는데 Data dd(10)을 하면 T의 자료형
이 무엇인지 모르기 때문에 메모리 공간의 할당을 얼만큼 해줘야 하는지 모른다.그렇기때문에
객체를 생성할때 명시적으로 선언을 해주어야 한다. Data<int> dd(10);

클래스 템플릿의 선언과 정의 분리

template <typename T>
class Data{
 T data;
public:
 Data(T d);
 void SetData(T d);
 T GetData();
};

template <typename T>
Data<T>::Data(T d){
 data=d;
}
template <typename T>
void Data<T>::SetData(T d){
 data=d;
}
template <typename T>
T Data<T>::GetData(){
 return data;
}


Data<T>::Data(T d)
typename T로 정의된 템플릿의 생성자 및 멤버함수를 정의하는것이다.
Data::Data(T d) 와는 엄연히 다르다. 이것은 Data클래스의 정의이고
Data<T>::Data(T d)는 Data 클래스 템플릿의 정의이다.

4. 템플릿의 원리 이해
template <typename T> //typename T에 대해 다음에  정의하는
T add(T a, T b)                 //대상을 템플릿으로 선언한다.
{
   return a+b;
}

호출이 가능한 함수를 만들기 위한 하나의 틀이다. 템플릿은 컴파일러에 의해 처리가 된다.
템플릿을 기반으로 해서 만들어지는 실제 호출이가능한 함수를 가리켜 템플릿 함수라고 한다.
또한 템플릿 함수가 생성되는 현상을 함수 템플릿의 인스턴스화 라고 부른다.
사용자 삽입 이미지

<내가 돈주고 산 열혈강의 C++ ppt자료에서 캡춰>


템플릿을 처리해 주는 것은 컴파일러 이기 때문에 템플릿 클래스는 선언과 정의를 각각 다른 파일에 분리 시켜 놓을수 없다. 따라서 클래스 템플릿은 하나의 파일안에 선언과 정의가 함께 있어야 한다.
블로그 이미지

百見 이 不如一打 요 , 百打 가 不如一作 이다.

,

11장정리

C++프로그래밍/C++ 2007. 7. 26. 10:12

int main(){
 string str1="Good";
 string str2="Morning";
 string str3=str1+str2;

 cout<<str1<<endl;
 cout<<str2<<endl;
 cout<<str3<<endl;

 str1+=str2;
 if(str1==str3)
  cout<<"equal"<<endl;

 string str4;
 cout<<"문자열입력:";
 cin>>str4;
 cout<<"입력한 문자열출력:"<<str4<<endl;

 return 0;
}

 
이 메인 함수에 대한 string 클래스를 디자인 해라.
블로그 이미지

百見 이 不如一打 요 , 百打 가 不如一作 이다.

,

10장정리

C++프로그래밍/C++ 2007. 7. 24. 21:13

1. 연산자 오버로딩의 의미

#include <iostream>

using std::cout;
using std::endl;

class Point{
private:
 int x,y;
public:
 Point(int _x=0, int _y=0) :x(_x),y(_y){}
 void ShowPosition();
 void operator+(int val);
};

void Point::ShowPosition(){
 cout<<x<<' '<<y<<endl;
}

void Point::operator+(int val){
 x+=val;
 y+=val;
}

int main(){
 Point p(3,4);
 p.ShowPosition();
 p.operator+(10);  // p+10;
 p.ShowPosition();

 return 0;
}

p객체를 생성하면서 3.4로 초기화 시켜주고 p의 멤버함수 operator+를 호출하면서 10을
인자로 전달해주고있다. operator+함수는 클래스 멤버변수의 값에 매개변수를 더해주고있다.

C++의 연산자 오버로딩은 하나의 약속일뿐이다.p+10 <-이것은 원래대로 라면 객체와 정수를 더하는 연산인데 이게 가능한가? 불가능하다.그래서 정한 약속에 불과할 뿐이다.
+기호 앞에operator이라는 이름을 붙여서 일반의 +와 오버로딩을 시키는 것이다.
결국 p+10 이란 문장은 p.operator+(10) 해석이 된다.이것은 곧 멤버함수에 의한 연산자 오버로딩에 해당된다.

2. 연산자를 오버로딩 하는 두가지 방법
멤버함수에 의한 연산자 오버로딩

class Point{
private:
 int x,y;
public:
 Point(int _x=0, int _y=0) :x(_x),y(_y){}
 void ShowPosition();
};

void Point::ShowPosition(){
 cout<<x<<' '<<y<<endl;
}

이러한 함수로 객체와 객체를 더해서 객체에 대입해 주고자 한다..무슨말이냐면 ㅋㅋ

int main(){
 Point p1(1,2);
 Point p2(2,3);
 Point p3=p1+p2;
 p3.ShowPosition();
 return 0;
}


이런 연산을 하고 싶단말이지..그럼 저건 어떤식으로 해야 가능할까?
함수를 정의해 보자고..우선 두개다 객체야..그럼 인자로 객체를 받아야할테고..
자 써보자고 operator+(Point& P) 이렇게 받는 객체를 생성해야지..
그리고 몸체부분에서 새로운 객체를 하나 생성해주고 temp로 그 temp생성할때
매개변수를 p1.p2의 x,y를 더한값을 주고 temp를 리턴해.

Point operator+(Point& p){ //(Point p)로넘겨주어도 되나 메모리의 사용에 효율을위해
   Point temp(x+p.x,y+p.y);
   return temp;
}


전역함수에 의한 오버로딩
위의 Point p3=p1+p2; 이 연산을 전역함수로 선언할 경우는 위의 멤버함수의 연산자 오버로딩과 형태가 달라진다.
사용자 삽입 이미지
<내가 돈주고산 열혈강의C++ ppt에서 캡춰>

이렇다는것을 알아두길 바라고..그럼 전역함수로 연산자 오버로딩을 하려면?
일단 저거 보면 연산자오버로딩 함수가 객체 두개를 인자로 받고 있다..그럼
operator+(Point& p1,Point& p2) 로 전달을 해줘야 하겠지..그럼 전체적으로 써볼까..
Point operator+(Point& p1,Point& p2){
   Point temp(p1.x+p2.x , p1.y+p2.y);
   return temp;
}

이렇게 해줘야..된닷!! 그런데 여기서..전역함수 이니까..멤버함수에 접근할려면
객체 내에서 friend선언 을 해줘야 하는것을 잊지 말라규~~

위와같이 멤버함수에서의 사용법과 전역함수에서의 사용법중 어떤게 좋을까.



객체지향에는 전역이라는 개념이 존재하지 않는다.




오버로딩이 불가능한 연산자의종류

.         .*         ::         ?:         sizeof


연산자 오버로딩에 있어서의 주의사항
첫째.본 의도를 벗어난 연산자 오버로딩은 좋지않다.
둘째.연산자 우선순위와 결합성을 바꿀수는 없다.
셋째.디폴트 매개변수 설정이 불가능하다.
넷째.디폴트 연산자들의 기본 기능까지 빼앗을 수는 없다.

3.단항연산자의 오버로딩
증가 감소 연산자의 오버로딩

사용자 삽입 이미지

<내가 돈주고산 열혈강의C++ ppt에서 캡춰>


이 소스를 보고 이해해라 어려운건 아니니..그런데 ++(++p)나 --(--p)연산의 함수를 보면
리턴타입이 레퍼런스 인 이유는 레퍼런스로 리턴받지 않으면 리턴값이 그냥 복사만 되기때문에 p의 값은 한번밖에 연산이 되지않고 나머지 한번의 연산은 복사본을 가지고 하는 연산이다. 그렇기때문에 레퍼런스로 넘겨주어야 p를 두번 연산할수 있는것이다.

선 연산과 후 연산의 구분
 
사용자 삽입 이미지
<내가 돈주고산 열혈강의C++ ppt에서 캡춰>

위와 같이 연산 할때와 연산 할때의 연산자 오버로딩의 매개변수가 다르다.
연산을 위한 함수를 오버로딩 할경우 키워드int를 매개변수로 선언하면 이것은 연산을
뜻하는 것으로 해석함. 여기서 int는 키워드 이다.

Point& Point::operator++(){
 ++x;
 ++y;
 return *this;
}
Point Point::operator++(int){
 Point temp(x,y); //point temp(*this);
 x++;
 y++;
 return temp; //여기서는 레퍼런스로 넘기면 안된다 왜냐면 temp객체는 함수지역객체이
}                 //기 때문에 함수가 종료됨과 동시에 사라지게 된다..그래서 복사로넘겨야
                  //한다. 이런 자질구레한 것까지 신경써야 좋은프로그래밍을 할수있겠지?

4. 교환법칙 해결하기
int a=3+4; 의 경우 3과4는 변경되지 않고 3+4의 값만이 a에 대입이 되는것이다.그런데
맨위의 예제에서 보면

Point p(3,4);
p+10;


이 operator+함수는 분명 p를 변경시키고 있다.제대로 표현하기 위해서는
operator+함수 안에서 새로운 객체를 생성후 그 객체의 인자로 val값과 x,y값을 더한값을 주어 그 객체를 리턴하면 된다. 그럼p를 변경시키지 않고 원하는 결과를 얻을수 있다.

만약에 위의 문장 p+10; 이것이 10+p; 가 된다면 어떻게 될까? 10은 분명히 객체가 아닌데...
이것도 따로 정의 해주어야 한다..;;이럴경우는 전역함수로 하는 수 밖에 없다.
operator+(int val,Point& p) 이렇게 넘겨 주어서 함수내에서 연산후 리턴해줘야 한다.
그냥 리턴값을 단순히 위치만 바꿔서 p+10을 리턴해주어도 되고 함수내에서 객체 생성후 인자로 멤버변수값과 val값을 전달한 객체를 리턴해주어도 되고..방법은 여러가지!

임시 객체의 생성..(나..원 -_-;;별...)
임시객체 생성문법
Point(3.4);
이름이 없다..생성되고 바로 다음줄에서 소멸된다.
임시객체를 사용할경우 컴파일러에 따라서 프로그램 최적화가 진행된다.

5. cin.cout.endl의 비밀

#include <stdio.h>

namespace mystd{
 char* endl="\n";
 class ostream
 {
 public:
  ostream& operator<<(char* str){
   printf("%s",str);
   return *this;
  }
  ostream& operator<<(int i){
   printf("%d",i);
   return *this;
  }
  ostream& operator<<(double i){
   printf("%e",i);
   return *this;
  }
 };
 ostream cout;
}

using mystd::cout;
using mystd::endl;

int main(){
 cout<<"hello world"<<100<<endl;
 cout<<100;
 return 0;
}

this포인터의 값을 넘겨주고 레퍼런스로 받는 이유는 다음연산을 위해서 이다.

<< , >> 연산자 오버로딩

ostream& operator<<(ostream& a,Point& p){
 a<<p.x<<' '<<p.y<<endl;
 return a;
}

int main(){
 Point p(1,3);
 cout<<p;
 return 0;
}


이거보고 알아서 파악해..힘들다.
메인함수의 cout<<p는 cout.operator<<(p) 인데 객체 p는 우리가 정의해준거다 .그러므로 표준에는 들어있지 않기때문에 멤버함수에선 불가능 하고 전역함수로 우리가 선언해주자
operator<<(cout,p)이걸 받을수 있게 해주면 될거 아니야 리턴은 꼭 레퍼런스로..또써먹을려면..

6. 배열의 인덱스 연산자 오버로딩의 예
기본자료형 데이터를 저장할수 있는 배열 클래스

arr[i] = arr.operator[](i)
객체를 저장할수 있는 배열 클래스

7.반드시 해야만 하는 대입연산자의 오버로딩

#include <iostream>

using std::cout;
using std::endl;
using std::ostream;

class Point{
 int x,y;
public:
 Point(int _x=0,int _y=0) : x(_x),y(_y){}
 friend ostream& operator<<(ostream& os,const Point& p);
};

ostream& operator<<(ostream& os, const Point& p){
 os<<"["<<p.x<<","<<p.y<<"]";
 return os;
}

int main(){
 Point p1(1,3);
 Point p2(10,30);
 cout<<p1<<endl;
 cout<<p2<<endl;

 p1=p2;
//p1=p2=p3; 이런 문장이 있을경우를 생각해보자 분명 연산자를 오버로딩
시켜서 해결해야만 할것이다..
 cout<<p1<<endl;
 return 0;
}

p1=p2;의 경우 디폴트 대인연산자가 제공이 된다(프로그래머가 대입 연산자를 정의해 주지 않으면) 디폴트 대입 연산자의 기능은 멤버대 멤버변수의 복사가 이루어진다.
이것은 디폴트복사 생성자와 비슷하다. 가지고 있는 문제점도 디폴트 복사생성자와 거의 같다...예제를 보며 알아서 찾아내라 오늘은 영..~~기분이 안나네 ㅋㅋ

1번소스는 문제 있는 코드
2번소스는 문제 고친 코드
사용자 삽입 이미지
<내가 돈주고산 열혈강의C++ ppt에서 캡춰>

이것도 동적할당을 할땐 문제가 되지..알아서 잘 해결해 언제까지 내가 이렇게 알려줄순
없잔아.ㅋㅋ  hint 깊은복사
ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
블로그 이미지

百見 이 不如一打 요 , 百打 가 不如一作 이다.

,

9장정리

C++프로그래밍/C++ 2007. 7. 22. 19:48

1. 클래스 멤버함수는 사실 어디에?

#include <iostream>

using std::cout;
using std::endl;

class Data{
 int data;
public:
 Data(int num){
  data=num;
 }
 void ShowData(){
  cout<<"Data : "<<data<<endl;
 }
 void add(int num){
  data+=num;
 }
};

int main()
{
 Data ddd(10);
 ddd.add(10);
 ddd.ShowData();

 Data eee(20);
 eee.add(20);
 eee.ShowData();

 return 0;
}

2개의 객체를 생성할 경우 멤버함수도 2번 호출하는데 이는 생성되는 객체마다 멤버함수가
존재하는 것이 아니다. 함수이름은 메모리 상에 존재하는 함수를 가리키는 포인터와 같다.
(상수포인터). 컴파일을 할때 이미 메모리 상에 올라간후 런타임에 함수포인터를 이용하여
불러온다고 해야하나..맞나..아무튼 객체를 100개 생성하더라도 메모리에 올라가는 함수는
하나이고 그 100개의 객체는 함수포인터로 메모리에 올라가있는 함수를 호출하여 사용한다.
즉 모든 객체가 함수 하나를 공유하는 형태를 취한다.

2. 가상함수가 동작하는 원리

 #include <iostream>

using std::cout;
using std::endl;

class A{
 int a;
 int b;
public:
 virtual void fct1(){cout<<"fct1()"<<endl;}
 virtual void fct2(){cout<<"fct2()"<<endl;}
};
class B : public A{
 int c;
 int d;
public:
 virtual void fct1(){cout<<"Overriding fct1()"<<endl;}
 void fct3(){cout<<"fct3()"<<endl;}
};

int main()
{
 A* aaa= new A();
 aaa->fct1();

 B* bbb=new B();
 bbb->fct1();
 return 0;
}

A클래스에 가상함수가 2개가 존재한다. 저렇게 1개 이상의 클래스를 포함하는 클래스에 대해서 컴파일러는 가상함수 테이블이라는 것을 만들어준다. 이 테이블은 실제 호출되어야할 함수의 위치정보를 가지고 있는 테이블이다.

사용자 삽입 이미지

<가상함수테이블>
<내가 돈주고 산 열혈강의 C++ ppt자료에서 캡춰>


가상함수 테이블은 key와value가 있는데 key값은 호출하고자 하는 함수를 구분지어주는것이고 value는 해당 함수의 위치를 가르쳐 주는 역할을 한다.

위의 예제에서 객체를 생성하면 다음과 같은 현상이 벌어지게 된다.

사용자 삽입 이미지

<가상함수 테이블과 가상함수와의 관계>
<내가 돈주고 산 열혈강의 C++ ppt자료에서 캡춰>



하나이상의 가상함수를 멤버로 지니는 클래스 객체는 가상함수 테이블을 가리킬수 있는 포인터가 추가된다.
가상함수를 포함하지 않은 클래스는 가상함수 테이블을 생성하지 않는다.

3. 다중상속에 대한이해
다중 상속이란 하나의 Derived 클래스가 둘이상의 Base를 상속하는것을 말한다.

#include <iostream>

using std::cout;
using std::endl;

class AAA{
public:
 void String1(){
  cout<<"AAA::String1()"<<endl;
 }
};

class BBB{
public:
 void String2(){
  cout<<"BBB::String2()"<<endl;
 }
};

class CCC : public AAA,public BBB{
public:
 void ShowString(){
  String1();
  String2();
 }
};

int main(){
 CCC ccc;
 ccc.ShowString();
 return 0;
}


클래스 CCC는 클래스 AAA와BBB를 동시에 상속하고 있다.
별 문제 없는 코드이다..실행결과도 아주 만족하게 나오고... 그! 러! 나!

#include <iostream>

using std::cout;
using std::endl;

class AAA{
public:
 void String1(){
  cout<<"AAA::String1()"<<endl;
 }
};

class BBB :  public AAA{
public:
 void String2(){
  cout<<"BBB::String2()"<<endl;
 }
};

class CCC :  public AAA{
public:
 void String3(){
  cout<<"CCC::String3()"<<endl;
 }
};

class DDD : public BBB, public CCC{
public:
 void ShowString(){
  String1();
  String2();
  String3();
 }
};
int main(){
 DDD ddd;
 ddd.ShowString();
 return 0;
}


이경우를 살펴보자. 클래스 BBB와 CCC는 각각 클래스 AAA를 상속하고 있다.
그런가운데 우리의 DDD씨는 BBB와CCC의클래스를 상속하고 계시군요! ㅋ
자..그럼 생각해봅시다. BBB와 CCC클래스는 각각 AAA클래스를 상속하고 있으니 둘다
String1()이라는 함수를 가지고 있겠지..그런 B,C클래스를 상속한 D클래스는
String1()함수를 2개나 갖게 된다..그래서 메인함수에서 저렇게 호출을 해버리면
어떤 String1()을 호출해야할지를 몰라서..오류를 뿜어내고 만다..우어~~
그럴경우 B,C클래스에서 A를 상속할떄 virtual상속을 하면 되는데(virtual base클래스)
쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지

블로그 이미지

百見 이 不如一打 요 , 百打 가 不如一作 이다.

,