如何建设一个门户网站,企业域名免费申请,土石方工程网站,wordpress声明1. 初始化列表
初始化列表在三种情况下必须使用:
继承关系下#xff0c;父类没有无参构造函数情况
#include iostreamusing namespace std;class Base{
public:string name;int num;Base(){cout 基类的无参构造... endl;}Base(string …1. 初始化列表
初始化列表在三种情况下必须使用:
继承关系下父类没有无参构造函数情况
#include iostreamusing 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...需要初始化const修饰的类成员或初始化引用成员数据
#include iostreamusing 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 iostreamusing 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 派生类的无参构造... endl;
// }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 iostreamusing 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...2. 重写父类同名函数
在C中子类可以重写override父类的同名函数。这被称为函数的覆盖function overriding。当子类重写父类的函数时它必须具有相同的名称、参数列表和返回类型。
特点 多态性通过重写父类函数子类对象可以根据实际类型来调用不同的函数实现实现多态性。继承性子类继承了父类的函数并且可以对其进行更改或增加新的功能。 使用场景 扩展功能子类可以通过重写父类函数来添加额外的行为或修改原有行为从而实现功能扩展。自定义实现子类可以根据自己的需求提供不同于父类的实现逻辑。适应特定情境根据特定场景需要在子类中针对某些特殊情况重新定义父类方法。 代码 #include iostream// 父类
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;
}3. 多继承
在C中子类多继承是指一个派生类从多个基类继承特性和行为。这意味着一个子类可以同时拥有多个父类的成员和方法。
特点 子类可以获得多个基类的属性和方法增强了代码复用性。多继承可以构建更复杂的继承关系允许在一个子类中结合不同的功能。多继承提供了更大的灵活性使得对象之间可以共享接口和实现。 使用场景 当存在一种逻辑上属于不同概念、但具有共同行为的情况时可以使用多继承来实现。当需要通过组合不同功能或角色来创建一个新的对象时也可以考虑使用多继承。 代码实现
#include iostream// 基类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;
}
3.1 多继承的构造函数
多继承形式下的构造函数和单继承形式基本相同只是要在子类的构造函数中调用多个父类的构造函数 。 他们调用的顺序由定义子类时继承顺序 决定。
#include iostreamusing 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类的析构构造...4. 类的前置声明
C中的类前置声明是指在使用类之前提前声明类的存在而不需要完整地定义类。它可以在某些场景下用于解决循环依赖或减少编译时间的问题。
特点 允许在程序中引用尚未完整定义的类。只需要提供类名和分号即可进行声明无需包含类的详细实现。前置声明通常用于解决循环依赖或减少编译时间。 使用场景
解决循环依赖 当两个或多个类相互引用时可以使用前置声明来解决循环依赖的问题。通过提前声明类的存在可以在类定义之前使用该类的指针或引用。
注意 B b // 报错,是因为不知道前面的声明的B类有没有无参构造 B* b; // 这是指针它只是一个地址而已不会执行无参构造。 B b; // 这是别名不创建对象所以不会执行无参构造。
#include iostreamclass 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 iostream// 前置声明
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;
}5. 继承的使用场景
代码重用和封装当多个类具有相似的属性和行为时可以将这些共同特征提取到一个基类中派生类继承基类以获得这些共同特征并在派生类中添加额外的特定功能。
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;
}