C++ 상속 심화

2023. 11. 30. 16:24C++

c++에서 클래스의 접근 속성 공통점과 차이점

여러개의 기본 클래스를 상속

#include <iostream>
using std::cout;
using std::endl;
class A1 // 아버지
{
	int a;
public:
	A1(int i) { a = i; }
	int getA() { return a; }
};
class A2 // 어머니
{
	int b;
public:
	A2(int i) { b = i; }
	int getB() { return b; }
};
class B :public A1, public A2
{
	// 기본 클래스 A1과 A2로부터
	// 상속 받은 파생 클래스
	int c;
public:
	B(int i=1, int j=1, int k) :A1(i), A2(j) { c = k; }
	// i는 기본클래스 A1의 생성자로,
	// j는 기본클래스 A2의 생성자로
	// 각각 매개변수 전달
	void show() {
		cout << getA() << ' ' << getB() << ' ' << c << endl;
	}
};
int main()
{
	B bb(1, 2, 3);
	bb.show();
	return 0;
}

여러개의 클래스 상속 시 생성자,소멸자 순서

#include <iostream>
using std::cout;
class A1 // 기본 클래스 1
{
	int a;
public:
	A1() { cout << "A1의 생성자.\n"; }
	~A1() { cout << "A1의 소멸자.\n"; }
};
class A2 // 기본 클래스 2
{
	int b;
public:
	A2() { cout << "A2의 생성자.\n"; }
	~A2() { cout << "A2의 소멸자.\n"; }
};
class B : public A1, public A2
	// 기본 클래스 1과 2로부터
	// 상속 받은 파생 클래스
{
	int c;
public:
	B() { cout << "B의 생성자.\n"; }
	~B() { cout << "B의 소멸자.\n"; }
};
int main()
{
	B bb;
	return 0;
}

이름과 전화번호 관리 

#include <iostream>
using std::cout;
#include <string>
class Name { //기본 클래스는 이름만 처리
	std::string name;
public:
	void get_name(std::string s) { name = s; }
	void print_name() { cout << name << "의 전화번호는"; }
};
class Phone : public Name { //파생클래스는 전화번호처리
	std::string phone;
public:
	void get_phone(std::string s) { phone = s; }
	void print_phone() {
		print_name();
		cout << phone;
	}
};
int main()
{
	Phone h;
	h.get_name("Smile Han");
	h.get_phone("1234-5678");
	h.print_phone();
	return 0;
}

 

#include <iostream>
using std::cout;
using std::string;//using문으로 string앞에 std::을 쓰지 않아도 된다.
class Man { //기본 클래스는 이름만 처리
	string name;
	int age;//Man의 멤버 변수는 string형 name과 int형 age
public:
	Man(std::string name, int age)
	{
		this->name = name;
		this->age = age;
	}
	void printMan()//Man의 이름과 나이를 출력하는 함수
	{ 
		cout <<"이름: "<<name<<"\n"<<"나이: "<<age<<"\n";
	}
};

class Student : public Man
{
	string ban;
	string hak;
public:
	Student(string name, int age, string ban, string hak) :Man(name, age)
	{//기본 클래스의 Man클래스의 생성자에게 매개변수를 넘겨주기 위해 작성
		this->ban = ban;
		this->hak = hak;
	}
	void s_show()//반과 학번 출력하는 함수
	{
		printMan();//상속받은 함수 호출
		cout << "반: " << ban << "\n" << "학번: " << hak << "\n";
	}
};

class Teacher : public Man
{
	string major;
	string subject;
public:
	Teacher(string name, int age, string major, string subject) :Man(name, age)
	{
		this->major = major;
		this->subject = subject;
	}
	void t_show()
	{
		printMan();
		cout << "전공: " << major << "\n" << "담당과목: " << subject << "\n";
	}

};

int main()
{
	Student kks("김컴소", 20, "C반", "202012000");
	Teacher hsh("한미소", 40, "전산", "C++프로그래밍");
	kks.s_show();
	hsh.t_show();
	return 0;
}

위 소스의 클래스 다이어그램

함수 오버로딩, 오버라이딩

  • 오버로딩(Overloading): 오버로딩은 같은 이름의 함수를 여러 개 정의하는 것을 의미합니다. 이때 함수들은 매개변수의 타입이나 개수가 달라야 합니다. 즉, 함수의 시그니처는 같지만 매개변수가 다른 함수를 여러 개 정의할 수 있습니다. 오버로딩을 사용하면 같은 이름의 함수를 다양한 상황에서 사용할 수 있어 코드의 가독성이 높아집니다
  • 오버라이딩(Overriding): 오버라이딩은 상속 관계에 있는 기본 클래스와 파생 클래스 사이에서 같은 이름, 같은 매개변수를 가진 멤버 함수를 재정의하는 것을 의미합니다. 이를 통해 기본 클래스의 함수를 파생 클래스에서 필요에 따라 다르게 동작하도록 변경할 수 있습니다.

함수 오버라이딩 예제

#include <iostream>
using std::cout
;
class Dot {
public:
	virtual void draw() 
	{
		cout << "Dot::draw()\n";
	}
	void print() 
	{
	cout << "Dot 클래스\n";
	draw();
	}
};
class Line :public Dot {
public:
	void draw() 
	{
		cout <<"Line::draw()\n";
	}
};
int main()
{
	Line line;
	line.print();
	return 0;
}

기본 클래스의 함수 draw()앞에 virtual을 붙이면 파생 클래스에서 재정의가 가능하다.

 

#include <iostream>
using std::cout;
class Dot {
public:
	virtual void draw()
	{
		cout << "Dot::draw()\n";
	}
	void print()
	{
		cout << "Dot 클래스\n";
		draw();
	}
};
class Line :public Dot {
public:
	void draw() override {
		cout << "Line::draw()\n";
	}
};
int main()
{
	Line line;
	line.print();
	return 0;
}

'C++' 카테고리의 다른 글

C++ reference, 형식 설정 멤버함수, 파일 입출력  (0) 2023.12.14
C++ 템플릿  (0) 2023.12.07
c++ 상속  (1) 2023.11.23
c++ 함수 중첩, 디폴트 인자  (0) 2023.11.16
C++ Const, 동적 메모리 할당  (0) 2023.11.09