내 연락처 정보
우편메소피아@프로톤메일.com
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
조합이 뭐야?
(1) 합성이란 여러 다른 클래스의 객체를 클래스 내의 멤버로 사용하는 것을 의미합니다.
(2) 클래스 트리를 사용하여 사례 설명
(3) 조합도 코드 재사용 방법이며 그 본질은구조포함하다
#include <iostream>
#include <vector>
#include <string>
// Leaf 类
class Leaf {
public:
Leaf(const std::string& color) : color_(color) {
std::cout << "Leaf constructor called: " << color_ << std::endl;
}
~Leaf() {
std::cout << "Leaf destructor called: " << color_ << std::endl;
}
void display() const {
std::cout << "Leaf color: " << color_ << std::endl;
}
private:
std::string color_;
};
// Branch 类
class Branch {
public:
Branch(int length) : length_(length) {
std::cout << "Branch constructor called: " << length_ << " cm" << std::endl;
}
~Branch() {
std::cout << "Branch destructor called: " << length_ << " cm" << std::endl;
}
void display() const {
std::cout << "Branch length: " << length_ << " cm" << std::endl;
}
private:
int length_;
};
// Tree 类,包含 Leaf 和 Branch 对象
class Tree {
public:
Tree(const std::string& leafColor, int branchLength)
: leaf_(leafColor), branch_(branchLength) {
std::cout << "Tree constructor called" << std::endl;
}
~Tree() {
std::cout << "Tree destructor called" << std::endl;
}
void display() const {
leaf_.display();
branch_.display();
}
private:
Leaf leaf_;
Branch branch_;
};
int main() {
Tree tree("Green", 150);
tree.display();
return 0;
}
상속과 구성의 특성 비교
(1) 상속은 일종의 (~이다 a) 관계는 추이적이며 대칭적이지 않습니다.
(2) 결합은 (가)의 부분의 관계이고,
(3) 상속은 화이트박스 재사용입니다. 클래스 상속을 통해 자체 구현에 따라 상위 클래스의 구현 세부 사항을 재정의할 수 있으므로 상위 클래스의 구현이 하위 클래스에 표시됩니다.
(4) 상속의 화이트박스 재사용 기능은 상위 클래스의 구현 세부 사항을 하위 클래스에 노출시키기 때문에 클래스의 캡슐화 기능을 어느 정도 파괴합니다.
(5) 조합은 블랙박스 재사용에 속합니다.포함된 객체의 내부 세부 사항은 외부 세계에 보이지 않으므로 캡슐화가 상대적으로 좋고 구현의 상호 의존성이 상대적으로 작습니다.
(6) 조합에 포함된 클래스는 포함하는 클래스가 생성됨에 따라 생성되고 소멸됩니다. 조합은 블랙박스 재사용이며 동일한 유형의 다른 개체 참조나 포인터를 가져와 런타임에 동적으로 정의할 수 있습니다. 단점은 시스템에 개체가 너무 많다는 것입니다.
(7) OO 디자인 원칙은 먼저 결합한 다음 상속하는 것입니다.
다중 상속
(1) 다중 상속은 하위 클래스에 여러 개의 상위 클래스가 있음을 의미합니다.
(2) 다중 상속 데모
(3) 다중 상속과 단일 상속의 원칙에는 뚜렷한 차이가 없습니다.
(4) 다중 상속은 모호성 문제를 초래할 수 있습니다.
다중 상속의 모호함 1
(1) 시나리오: C는 A와 B로부터 다중 상속을 받기 때문에 C에서 A와 B의 동일한 이름으로 멤버를 호출하면 모호성이 발생합니다.
(2) 이유: C는 A와 B에서 동일한 이름(다른 네임스페이스 도메인)을 가진 멤버를 상속하므로 C의 개체로 호출할 때 컴파일러는 어느 개체를 호출할지 결정할 수 없습니다.
(3) 해결 방법 1: 이러한 현상이 발생하지 않도록 A와 B의 공개 멤버 이름이 반복적으로 충돌하지 않도록 합니다. 그러나 이것은 때때로 통제할 수 없는 일이다.
(4) 해결 방법 2: 코딩 시 어느 것을 호출할지 명확하게 지정하고, cA::func()를 사용하여 클래스 B의 func 대신 클래스 A의 func가 호출되도록 명확하게 지정합니다.
(5) 해결 방법 3: C에서 func를 재정의하면 C의 func가 호출되고 A와 B의 func는 숨겨집니다.
(6) 요약: 해결될 수 있지만 좋은 해결책은 없습니다.
다중 상속의 모호함 2
(1) 시나리오: 다이아몬드 상속 문제.즉, A는 조상 클래스인 B1:A, B2:A, C:B1,B2입니다. 이때 C의 객체를 사용하여 A의 메서드를 호출하면 모호성이 발생합니다.
(2) 분석: c.func()는 모호하고 cA::func()도 모호하지만 c.B1::func() 및 c.B2::func()는 모호하지 않습니다.
(3) 해결 방법: 문제 1과 동일하지만 문제 2는 더 미묘하고 피하기가 더 어렵습니다.
// 祖类
class Aa {
public:
void show() { std::cout << "A's method" << std::endl; }
};
// 派生类 B1 和 B2,从 A 继承
class B1 : public Aa {
public:
void show() { std::cout << "B1's show" << std::endl; }
void showB1() { std::cout << "B1's method" << std::endl; }
};
class B2 : public Aa {
public:
void show() { std::cout << "B2's show" << std::endl; }
void showB2() { std::cout << "B2's method" << std::endl; }
};
// 派生类 C,从 B1 和 B2 继承
class C : public B1, public B2 {
public:
void showC() { std::cout << "C's method" << std::endl; }
};
int test070103() {
C c;
// c.Aa::show(); // 调用 A 的方法 不可以
c.Aa::B1::show(); // 调用 A 的方法 不可以
c.B2::Aa::show(); // 调用 A 的方法 不可以
c.B1::show(); // 调用 B1 的方法
c.B2::show(); // 调用 B2 的方法
c.showB1(); // 调用 B1 的方法
c.showB2(); // 调用 B2 的方法
c.showC(); // 调用 C 的方法
return 0;
}
가상 상속을 사용하는 방법
(1) 시나리오: 다이아몬드 상속으로 인해 모호성 문제가 발생합니다. 본질적으로 손자 클래스 C에는 B1과 B2에 두 개의 A 객체가 포함되어 있으므로 모호성이 있습니다.
(2) 가상 상속 솔루션: B1과 B2가 A를 가상으로 상속하게 하면 C는 B1과 B2를 정상적으로 상속할 수 있습니다.
(3) 가상 상속은 다이아몬드 상속의 모호성 문제를 해결하기 위해 만들어졌습니다. (다형성 기능을 달성하기 위해)
가상 상속의 구현 원리
(1) 가상 상속의 원칙은 다음과 같습니다: 가상 기본 클래스 테이블 포인터 vbptr 및 가상 기본 클래스 테이블 가상 테이블
(2) 참고:https://blog.csdn.net/xiejingfa/article/details/48028491
클래스 클래스에는 다른 클래스 유형의 멤버 변수가 많이 있습니다.
구성과 상속의 차이점 이해
모호성: 함수를 실행하는 경우 반드시 지정하려는 함수가 아닐 수도 있습니다.
해결책: cA::func()를 사용하여 호출되는 클래스를 명시적으로 지정합니다.
가상 상속은 조건부 컴파일과 비슷합니다. 한 번만 도입하면 도입 효과를 얻기 위해 반복적으로 도입할 필요가 없습니다.
연구 기록 및 침해 연락처가 삭제됩니다.
출처: 주 선생님의 사물 인터넷 교실