Inheritance
composition
ways of inclusion
- fully has(是这个类独有的)
- by reference
用初始化列表
一般内部的object都是private, 但是如果要在外部调用它的成员函数,就设成public
client class
inheritance
access control
- public
- private可被本类成员和友元(friend)访问,不能被子类访问
- protected 可被子类访问 和friends访问
继承关系
Inheritance Type | public | protected | private |
---|---|---|---|
B: public A | public in B | protected in B | private |
B: private A | private in B | private in B | private |
B: protected A | protected in B | protected in B | private |
class A{
private:
int i;
protected:
int ii;
public:
A(){}
A(int _i){i=ii=_i;}
void print(){printf("%d %d\n",i,ii);}
~A(){}
};
class B: public A{//B是A的派生类
public:
void set(int x){
//i=x; 错误,不可访问
ii=x;//正确
}
};
如果父类和子类有相同的变量名,优先调用子类的。
c'tors
调用顺序: 1. 构造基类(可能继续递归下去,先构造基类的基类,基类的成员变量... 2. 成员变量的构造函数 3. 派生类的构造函数
What is not inherited?
- 构造函数没有被继承,但父类的构造会被自动调用。析构同理。
- 赋值的运算符不会被继承。
- 友元不会被继承
-
可以多继承(多个基类
-
先构造父类,再构造子类。会调用父类的默认构造函数对父类的变量进行初始化
- 子类不能访问父类的私有变量,但私有变量存在于这个类中。
如何对父类私有变量初始化?: 当调用子类的构造函数时,我们不能调用父类的私有变量,只能用初始化列表的方式调用父类的构造函数进行初始化。
function overload
当子类和父类有同名函数的时候
- 会调用自身重新定义的函数
- 在子类中重新定义函数后,父类所有重载的同名函数被隐藏,无法使用!
- 用virtual解决
#include<iostream>
#include<cstdio>
class A{
private:
int i;
protected:
int ii;
public:
A(){}
A(int _i){i=ii=_i;}
void print(){printf("A: i=%d ii=%d\n",i,ii);}
void print(int x){printf("%d :%d\n",x,i);}
~A(){}
};
class B: public A{
public:
void set(int x){
ii=x;//i=x; 错误,不可访问
}
void print(){
printf("B: %d\n",ii);
}
};
int main(){
B b;
b.set(20);
b.print();//输出B: 20 原因:子类中重新定义
b.print(10);//错误! 不能调用父类的print(int x)
//原因:重新定义子类的print之后,父类所有名字为print的函数被隐藏
A* ptr=&b;
ptr->print();//输出A: 0 20 原因: B中存在父类继承过来的i,但i未初始化(会报Warning)
}
friends
指定类或者函数,可以访问private和public
class B;//前向声明
class A{
private:
int numA
friend class B;//声明B是A的friend
public:
int add(B b){
return b.numB+numa;//错误,friend是单向的
}
};
class B{
private:
int numB;
public:
int add(A a){
return a.numA+numB;//因为B是A的friend,可以访问A的private numB:
}
};
全局函数是friend
class A{
int numA;
friend int addAB(class A,class B);//声明
};
class B{
int numB;
friend int addAB(class A,class B);//声明
};
int addAB(A a,B b){
return a.numA+b.numB;
}
习题
the output at //1 is 114 ; the output at //2 is 303062 ; the output at //3 is 115 ; the output at //4 is 303062
#include<bits/stdc++.h>
using namespace std;
class A{
int i;
public:
A(int ii=0):i(ii) { cout<<ii<<" "<< 1; }
A(const A& a) {
i = a.i;
cout << 2;
}
void print() const { cout << 3 << i; }
};
class B : public A {//继承,本身要调用一次A的构造函数
int i;
A a;//组合,再调用一次A
public:
B(int ii = 0) : i(ii) { cout << 4; }
B(const B& b) {
i = b.i;
cout << 5;
}
void print() const {
A::print();
a.print();
cout << 6 << i;
}
};
int main()
{
B b(2); //1
b.print(); //2
B c(b); //3
c.print(); //4
}