初始化列表在三种情况下必须使用:
#include
using namespace std;
class Base{
public:
string name;
int num;
Base(){
cout<< "基类的无参构造..." <<endl;
}
Base(string name){
cout<< "基类的有参构造1..." <<endl;
}
Base(string name,int num){
cout<< "基类的有参构造2..." <<endl;
}
};
class Derived : public Base {
public:
Derived(){
cout<< "派生类的无参构造..." <<endl;
}
Derived(string name):Base(name){
cout<< "派生类的有参构造1..." <<endl;
}
Derived(string name,int num):Base(name,num){
cout<< "派生类的有参构造2..." <<endl;
}
};
int main() {
Derived d;
cout << "------------------------" << endl;
Derived d0("zhangfei");
Derived d1("libai",24);
return 0;
}
运行结果:
基类的无参构造...
派生类的无参构造...
------------------------
基类的有参构造1...
派生类的有参构造1...
基类的有参构造2...
派生类的有参构造2...
#include
using namespace std;
class person{
public:
const int ID;
int & age;
person(int no , int age):ID(no),age(age){
cout << "执行构造函数..." <<endl;
}
};
int main(){
person p(78 , 28);
cout << p.ID << " , " << p.age << endl;
return 0 ;
}
#include
using namespace std;
class Base{
public:
string name;
int num;
Base(){
cout<< "基类的无参构造..." <<endl;
}
Base(string name){
cout<< "基类的有参构造1..." <<endl;
}
Base(string name,int num){
cout<< "基类的有参构造2..." <<endl;
}
};
class Derived{
public:
int no;
Base b;
// Derived(){
// cout<< "派生类的无参构造..." <
// }
Derived(string name):b(name){
cout<< "派生类的有参构造1..." <<endl;
}
Derived(string name,int num):b(name,num){
cout<< "派生类的有参构造2..." <<endl;
}
};
int main() {
cout << "------------------------" << endl;
Derived d0("zhangfei");
cout << "------------------------" << endl;
Derived d1("libai",24);
return 0;
}
运行结果:
------------------------
基类的有参构造1...
派生类的有参构造1...
------------------------
基类的有参构造2...
派生类的有参构造2...
or
#include
using namespace std;
class Base{
public:
string name;
int num;
Base(){
cout<< "基类的无参构造..." <<endl;
}
Base(string name){
cout<< "基类的有参构造1..." <<endl;
}
Base(string name,int num){
cout<< "基类的有参构造2..." <<endl;
}
};
class Derived{
public:
int no;
Base b;
Derived():b(){
cout<< "派生类的无参构造..." <<endl;
}
Derived(string name):b(name){
cout<< "派生类的有参构造1..." <<endl;
}
Derived(string name,int num):b(name,num){
cout<< "派生类的有参构造2..." <<endl;
}
};
int main() {
Derived d;
cout << "------------------------" << endl;
Derived d0("zhangfei");
cout << "------------------------" << endl;
Derived d1("libai",24);
return 0;
}
运行结果:
基类的无参构造...
派生类的无参构造...
------------------------
基类的有参构造1...
派生类的有参构造1...
------------------------
基类的有参构造2...
派生类的有参构造2...
在C++中,子类可以重写(override)父类的同名函数。这被称为函数的覆盖(function overriding)。当子类重写父类的函数时,它必须具有相同的名称、参数列表和返回类型。
- 多态性:通过重写父类函数,子类对象可以根据实际类型来调用不同的函数实现,实现多态性。
- 继承性:子类继承了父类的函数,并且可以对其进行更改或增加新的功能。
- 扩展功能:子类可以通过重写父类函数来添加额外的行为或修改原有行为,从而实现功能扩展。
- 自定义实现:子类可以根据自己的需求提供不同于父类的实现逻辑。
- 适应特定情境:根据特定场景需要,在子类中针对某些特殊情况重新定义父类方法。
代码:
#include
// 父类
class Shape {
public:
virtual void draw() {
std::cout << "绘制形状" << std::endl;
}
};
// 子类 Circle
class Circle : public Shape {
public:
void draw() override { // 使用 override 关键字表示重写
std::cout << "绘制圆形" << std::endl;
}
};
// 子类 Rectangle
class Rectangle : public Shape {
public:
void draw() override {
std::cout << "绘制矩形" << std::endl;
}
};
int main() {
Shape* shape1 = new Circle();
shape1->draw(); // 输出:绘制圆形
Shape* shape2 = new Rectangle();
shape2->draw(); // 输出:绘制矩形
delete shape1;
delete shape2;
return 0;
}
在C++中,子类多继承是指一个派生类从多个基类继承特性和行为。这意味着一个子类可以同时拥有多个父类的成员和方法。
- 子类可以获得多个基类的属性和方法,增强了代码复用性。
- 多继承可以构建更复杂的继承关系,允许在一个子类中结合不同的功能。
- 多继承提供了更大的灵活性,使得对象之间可以共享接口和实现。
- 当存在一种逻辑上属于不同概念、但具有共同行为的情况时,可以使用多继承来实现。
- 当需要通过组合不同功能或角色来创建一个新的对象时,也可以考虑使用多继承。
#include
// 基类A
class A {
public:
void funcA() {
std::cout << "This is function A." << std::endl;
}
};
// 基类B
class B {
public:
void funcB() {
std::cout << "This is function B." << std::endl;
}
};
// 子类C从基类A和基类B进行多继承
class C : public A, public B {
public:
void funcC() {
std::cout << "This is function C." << std::endl;
}
};
int main() {
C c;
c.funcA(); // 调用基类A的函数
c.funcB(); // 调用基类B的函数
c.funcC(); // 调用子类C自身的函数
return 0;
}
多继承形式下的构造函数和单继承形式基本相同,只是要在子类的构造函数中调用多个父类的构造函数 。 他们调用的顺序由定义子类时,继承顺序 决定。
#include
using namespace std;
// 基类A
class A {
public:
A(){
cout<< "A类的无参构造..." <<endl;
}
~A(){
cout<< "A类的析构构造..." <<endl;
}
};
// 基类B
class B {
public:
B(){
cout<< "B类的无参构造..." <<endl;
}
~B(){
cout<< "B类的析构构造..." <<endl;
}
};
// 子类C从基类A和基类B进行多继承
class C : public A, public B {
public:
C(){
cout<< "C类的无参构造..." <<endl;
}
~C(){
cout<< "C类的析构构造..." <<endl;
}
};
int main() {
C c;
return 0;
}
运行结果:
A类的无参构造...
B类的无参构造...
C类的无参构造...
C类的析构构造...
B类的析构构造...
A类的析构构造...
C++中的类前置声明是指在使用类之前提前声明类的存在,而不需要完整地定义类。它可以在某些场景下用于解决循环依赖或减少编译时间的问题。
- 允许在程序中引用尚未完整定义的类。
- 只需要提供类名和分号即可进行声明,无需包含类的详细实现。
- 前置声明通常用于解决循环依赖或减少编译时间。
B b // 报错,是因为不知道前面的声明的B类有没有无参构造
B* b; // 这是指针,它只是一个地址而已,不会执行无参构造。
B& b; // 这是别名,不创建对象,所以不会执行无参构造。
#include
class B; // 前置声明
class A {
private:
B* b;
public:
void setB(B* obj) {
b = obj;
}
void doSomething();
};
class B {
private:
A* a;
public:
void setA(A* obj) {
a = obj;
}
void doSomething();
};
void A::doSomething() {
std::cout << "a->doSomething()" << std::endl;
if (b) {
b->doSomething();
}
}
void B::doSomething() {
std::cout << "b->doSomething()" << std::endl;
if (a) {
a->doSomething();
}
}
int main() {
A a;
B b;
a.setB(&b);
b.setA(&a);
std::cout << "-----------------------------" << std::endl;
a.doSomething();
b.doSomething();
return 0;
}
类A和类B相互引用,并使用了前置声明。在类A中,成员变量B* b是一个指针类型,不会执行B类的无参构造函数,因此不需要知道B类是否有无参构造函数。而如果将成员变量声明为B& b,则是一个引用类型,也不会执行B类的无参构造函数。
在类定义之后,我们定义了类A和类B的成员函数doSomething()。在A::doSomething()中,调用了b->doSomething(),即调用了B类的成员函数。同样,在B::doSomething()中,调用了a->doSomething(),即调用了A类的成员函数。
在main()函数中,我们创建了类A和类B的对象,并通过setB()和setA()方法设置了它们之间的循环依赖关系。最后,调用了a.doSomething()和b.doSomething()来触发成员函数的调用。
#include
// 前置声明
class SomeClass;
void useSomeClass(SomeClass* obj);
int main() {
SomeClass* obj = new SomeClass();
useSomeClass(obj);
delete obj;
return 0;
}
// 完整类定义
class SomeClass {
public:
void doSomething();
};
void useSomeClass(SomeClass* obj) {
obj->doSomething();
}
void SomeClass::doSomething() {
std::cout << "Doing something..." << std::endl;
}
class Animal {
public:
void eat() {
std::cout << "Animal is eating." << std::endl;
}
};
class Dog : public Animal {
public:
void bark() {
std::cout << "Dog is barking." << std::endl;
}
};
int main() {
Dog dog;
dog.eat(); // 继承自Animal类
dog.bark(); // Dog类自身的函数
return 0;
}
class Shape {
public:
virtual void draw() {
std::cout << "Drawing a shape." << std::endl;
}
};
class Circle : public Shape {
public:
void draw() override {
std::cout << "Drawing a circle." << std::endl;
}
};
class Rectangle : public Shape {
public:
void draw() override {
std::cout << "Drawing a rectangle." << std::endl;
}
};
int main() {
Shape* shape1 = new Circle();
Shape* shape2 = new Rectangle();
shape1->draw(); // 动态调用Circle类的draw函数
shape2->draw(); // 动态调用Rectangle类的draw函数
delete shape1;
delete shape2;
return 0;
}
class Vehicle {
protected:
int wheels;
public:
Vehicle(int numWheels) : wheels(numWheels) {}
void printWheels() {
std::cout << "Number of wheels: " << wheels << std::endl;
}
};
class Car : public Vehicle {
public:
Car() : Vehicle(4) {}
void startEngine() {
std::cout << "Engine started." << std::endl;
}
};
int main() {
Car car;
car.printWheels(); // 继承自Vehicle类
car.startEngine(); // Car类自身的函数
return 0;
}