[11] Inheritance
Inheritance : is-a relationship
11.2継承の基礎
Studnet is a Person
Teacher is a Person
->
Child ClassにはMother Classが含まれているため、Mother Classが宣言した場合、Child Classで宣言する必要はありません.当たり前なら
クラスは、個別のヘッダファイルを作成して削除することが望ましい.
作成順序
常にMatherクラスを作成した後にChildクラスを生成します.
11.2に示すように、初期化器は親クラスのメンバーを初期化することはできません.これは,Child classのイニシエータがイニシャル化されるとMotherクラスの作成者が呼び出されるためである.つまり私たちの目には.
クラスを複数回継承する場合:
11.4 Derived Classの作成と初期化
Child classを生成すると、Child変数+がMotherに宣言したようにメモリサイズが割り当てられます.
11.5指定者の継承とアクセス
例を挙げると、
11.6ブートクラスに新しい機能を追加
Skip
11.7継承関数の上書き
継承された変数
2つ以上のレベルを継承すること.
クラスAはクラスB、Cを継承し、BとCが
以下の場合をダイヤモンド継承と呼びます.多重継承を誤って使用すると、次の問題が発生する可能性があります.
問題に対する解決法は多様な形で観察される.
11.2継承の基礎
Studnet is a Person
Teacher is a Person
->
Person
が普及しているので、Personクラスを再作成します.Child ClassにはMother Classが含まれているため、Mother Classが宣言した場合、Child Classで宣言する必要はありません.当たり前なら
クラスは、個別のヘッダファイルを作成して削除することが望ましい.
#include <bits/stdc++.h> //비추천. 편의상 작성
using namespace std; //비추천. 편의상 작성
//Person Class
class Person {
private:
std::string m_name;
public:
Person(const std::string& name_in = "No name") : m_name(name_in) {}
void setName(const string& name_in) {
//의도적인 막음.
m_name = name_in; //Person 에서 public 변수가 아니니까 당연함.
}
// const 선언 이유. Child 클래스에서 param 으로 받아오는데 param에서 const로 불러오고 있음.
string getName() const {
return m_name;
}
};
//Student Class
class Student : public Person {
private:
int m_intel;
public:
// 생성자에서 initialize 할 떄 에러가 남. m_name 은 Person 의 member variable.
// Student에서 Person 의 constructor를 초기화하는식으로 해야함
Student(const string& name_in = "no name", const int& intel_in = 0)
// : m_name(name_in), m_intel(intel_in) {}
: Person(name_in), m_intel(intel_in) {} //Studnet 생성자를 통해서 Person 생성자를 호출
// void setName(const string& name_in) {
// //의도적인 막음. Person의 m_name 을 자식에서 접근하지 않도록
// m_name = name_in; //Person 에서 public 변수가 아니니까 당연함.
// }
void setIntel(const int& intel_in) {
m_intel = intel_in;
}
int getIntel() const {
return m_intel;
}
friend ostream& operator << (ostream& out, const Student& student) {
// getName이 mother. Stduent 을 const로 params로 받아오므로, getName() 뒤에 const 선언
out << student.getName() << " " << student.getIntel();
// out << student.m_name << " " << student.m_intel;
return out;
}
void study() {
cout << getName() << " is studying" << endl;
}
};
//Teacher Class
class Teacher : public Person {
private:
public:
Teacher(const string& name_in = "no name")
: Person(name_in) {
}
friend ostream& operator << (ostream& out, const Teacher& teacher) {
out << teacher.getName(); //직접 접근 불가능
return out;
}
void teach() {
cout << getName() << " is teaching" << endl;
}
};
ChildクラスTeacherとStudioでnameを初期化する場合は、親クラスPersonクラスのジェネレータを直接呼び出して初期化できます.これについての説明は、次のChapterでさらに詳しく説明します.(ジェネレータ順序のため) Student(const string& name_in = "no name", const int& intel_in = 0)
: Person(name_in), m_intel(intel_in) {}
11.3 Derived Class作成順序作成順序
常にMatherクラスを作成した後にChildクラスを生成します.
11.2に示すように、初期化器は親クラスのメンバーを初期化することはできません.これは,Child classのイニシエータがイニシャル化されるとMotherクラスの作成者が呼び出されるためである.つまり私たちの目には.
Child() : m_d(1.0) {}
事実上.Child() : Mother(), m_d(1.0) {}
はい.Mother classのメンバー変数はジェネレータの{}
で呼び出すことができますが、initializerで呼び出すことはできません.クラスを複数回継承する場合:
class A {
public:
A() { cout << " A Constructor " << endl;}
};
class B : public A {
public:
B() { cout << " B Constructor " << endl;}
};
class C : public B {
public:
C() { cout << " C Constructor " << endl;}
};
A Constructor
B Constructor
C Constructor
この場合、Constructor
は当然A
となり、B
、C
の順に生成される.Destructor
はConstructor
の逆順である.11.4 Derived Classの作成と初期化
Child classを生成すると、Child変数+がMotherに宣言したようにメモリサイズが割り当てられます.
11.5指定者の継承とアクセス
例を挙げると、
Base
クラスは以下のようになります.class Base {
public:
int m_public;
// protected 는 child 만 접근 가능
protected:
int m_protected;
private:
int m_private;
};
class Derived : private Base
Derivedクラス内でBaseクラスのpublicおよびprivate変数にアクセスできますが、GrandChildクラス(つまりDerived Class)を継承するクラスでBaseのすべての変数にアクセスすることはできません.class Derived : private Base {
public:
int d_int;
Derived() {
m_public = 123;
m_protected = 321;
}
};
class GrandChild : public Derived {
public:
GrandChild() {
d_int = 123;
// Derived::m_public = 123; 불가
// Derived::m_protected = 123 ; 불가
}
};
class Derived : protected Base
クラス内ではBaseクラスのpublic変数やprotected変数にもアクセスできますが、外部(main)ではアクセスできません.11.6ブートクラスに新しい機能を追加
Skip
11.7継承関数の上書き
class Base {
private:
int m_val;
public:
Base(int val_) : m_val(val_) {}
void print() {
cout << "I'm base" << endl;
}
// output operator overrloading
friend ostream& operator << (ostream& out, const Base& b) {
cout << "this is base output" << endl;
return out;
}
};
class Derived : public Base {
private:
double m_d;
public:
Derived(int val_) : Base(val_) {}
// override 하고 싶을 때.
void print() {
cout << "I'm Derived" << endl;
}
// output operator overrloading
friend ostream& operator << (ostream& out, const Derived& b) {
//base operator 를 불러오고 싶을 때
//이게 왜 되냐? 메모리가 사이즈가 있으면,Base + Derived니까
//Base에 대한 내용을 Derived가 갖고 있기 때문에 가능함!
cout << static_cast<Base>(b);
cout << "this is derived output" << endl;
return out;
}
};
int main() {
Base base(5);
// base.print();
cout << base;
Derived derived(7);
// derived.print();
cout << derived;
}
11.8継承関数の非表示継承された変数
public
はクラス内で使用できます. // m_i 가 Derived 안에서 public이 되고, 외부에서 변경 가능함.
using Base::m_i;
逆に、継承された関数の使用が阻止される場合があります.//방법 1. private 선언 후, 작성
private:
using Base::print;
//방법 2. delete
private:
void print() = delete;
11.9継承数2つ以上のレベルを継承すること.
クラスAはクラスB、Cを継承し、BとCが
getID()
の関数を有し、getID関数を呼び出す必要がある場合.A a("test)";
a.B::getID();
a.C::getID();
これで呼びます.以下の場合をダイヤモンド継承と呼びます.多重継承を誤って使用すると、次の問題が発生する可能性があります.
問題に対する解決法は多様な形で観察される.
Reference
この問題について([11] Inheritance), 我々は、より多くの情報をここで見つけました https://velog.io/@gyeolse/11-inheritanceテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol