继承:继承是一种可以使代码复用的一种手段,允许在原有类的基础上产生新的类。
语法:在一个类后加上 : 继承方式 另一个类类名
继承方式:public,protected,private
class A
{
public:
void fun()
{
cout << "fun" << endl;
}
private:
int a;
};
class B :public A
{
public:
void print()
{
cout<<"print"<<endl;
}
private:
int b;
};
//B是派生类,A是基类
1.派生类的大小
派生类的大小:派生类的成员和基类的成员的总大小
class A
{
private:
int a;
int b;
int c;
};
class B :public A
{
private:
int b;//大小为4个int,16个字节
};
2.派生类继承基类,继承方式的权限是往里缩而不会往外扩的,public>protected>private。
class A
{
public:
void show()
{
cout << "show" << endl;
}
protected:
void swap()
{
cout << "swap" << end
}
private:
void fun()
{
cout << "fun" << endl
}
};
class B :protected A
{
public:
void print()
{
cout<<"print"<<endl;
}
};
int main()
{
B b;
b.show();//由于继承方式是protected,所以在基类A中原本public的show方法不能直接访问了,会出错
}
3.基类的私有成员在派生类是不允许直接被访问的,而共有成员和保护成员可以直接被访问,这也是私有和保护的区别
class A
{
public:
void show()
{
cout << "show" << endl;
}
protected:
void swap()
{
cout << "swap" << end
}
private:
void fun()
{
cout << "fun" << endl
}
};
class B :public A
{
public:
void print()
{
show();
swap();//在派生类可以直接访问基类的共有成员和保护成员
fun();//不能直接访问基类的私有成员
}
};
4.赋值语句规则
- 子类对象可以给父类对象赋值
- 子类对象的地址可以给父类对象的指针赋值
- 子类对象的引用可以给父类对象初始化
class A
{
public:
int a;
};
class B:public A
{
public:
int a;
};
int main()
{
B b;
A a;
a = b;
A*pa = &b;
A&qa = b;
return 0;
}
为什么可以赋值呢?来看一段代码
class A
{
public:
A()
{
cout << "A::A" << endl;
}
~A()
{
cout << "A::~A" << endl;
}
int a;
};
class B :public A
{
public:
B()
{
cout << "B::B" << endl;
}
~B()
{
cout << "B::~B" << endl;
}
int b;
};
int main()
{
B b;
return 0;
}
结果如下:
我们可以看到实例化了一个B对象,在调动B的构造函数时,会先调动A的构造函数,所以在b对象内部是有A的成员的.我们可以通过监视看到。
所以子类对象可以给父类赋值,是因为在子类里有父类成员。父类不能给子类赋值,因为父类里没有子类成员。这是赋值的本质。
当实例化一个子类对象,先调动基类的构造函数,再调动派生类的构造函数,析构时,先调动子类的析构函数,再调动基类的构造函数
5.同名函数
当派生类与有基类同名的函数时,会自动屏蔽掉基类的同名函数,只使用派生类的函数,如果一定要使用基类的函数: 派生类对象.基类::函数
class A
{
public:
void fun()
{
cout << "A::fun()" << endl;
}
void fun(int a)
{
cout << "A::fun(a)" << endl;
}
private:
int a;
};
class B :public A
{
public:
void fun()
{
cout << "B::fun()" << endl;
}
private:
int b;
};
int main()
{
B b;
b.fun();//子类的fun函数
b.fun(0);//错误,子类没有这个函数
b.A::fun(0);//父类的fun(int)函数
return 0;
}
6.友元不能继承
我们知道,如果一个方法想要访问类的私有成员,可以将这个方法设为友元
class A
{
friend void show(const A&a);
private:
int m = 0;
};
class B :public A
{
private:
int n = 0;
};
void show(const A&a)
{
cout << "m = " << a.m << endl;
}
int main()
{
A a;
B b;
show(a);
return 0;
}
而我们使用继承,用父类的友元函数访问子类的私有成员来试试
class A
{
friend void show(const A&a,const B&b);
private:
int m = 0;
};
class B :public A
{
private:
int n = 0;
};
void show(const A&a, const B&b)
{
cout << "m = " << a.m << endl;
cout << "n = " << b.n << endl; //不能通过编译,所以说明父类的友元并不能访问子类的私有成员
}
int main()
{
A a;
B b;
show(a,b);
return 0;
}
反过来也一样,子类的友元方法也不能访问父类的私有成员。
总结:友元在父子类中没有传递性,友元不能继承。