C++ 之 面向对象基础知识

面向过程设计

实际上就是模块化编程,简单来说就是程序 = 数据结构 + 函数,但是函数和变量是分开的也就是说property和behavior是分割的。

graph LR; A((结构化程序设计)) --> B((模块化编程))

面向对象设计

graph LR; A[一类事物] -->|抽象| B[共同属性 ] B --> C[数据结构] A -->|抽象| D[行为/操作] D --> E[函数] C -->|封装| F[类] E -->|封装| F[类]

类的定义

class 类名
{
    访问范围说明符:
        成员变量1
        成员变量2
        ···
        成员函数声明1
        成员函数声明2
    访问范围说明符:
        更多成员变量1
        更多成员变量2
        ···
        更多成员函数声明1
        更多成员函数声明2  
};

复制构造函数

class X{};
X::X(X &);
X::X(const X &);
X::X(X); //该构造函数形式不允许存在

作用

  1. 当用一个对象去初始化同类的另一个对象时。
  2. 如果某函数有一个参数是类A的对象,那么该函数被调用时,类A的复制构造函数将被调用。
  3. 如果函数的返回值是类A的对象时,则函数返回时,A的复制构造函数被调用

类型转换构造函数

目的:

  • 实现类型的自动转换
  • 特点
  • 只有一个参数
  • 不是复制构造函数
  • 编译系统会自动调用

转换构造函数
建立一个临时对象/临时变量

Exsample :

class Complex{
public:
    double real, imag;
    Complex(int i){
        cout << "IntConstructor called" <<endl;
        real = i;
        imag = 0;
    }
    Complex(double r,double i) {
        real = r;
        imag = i;
        }
};

int main(){
    Complex c1(7,8);
    Complex c2=12;
    c1=9;//9被自动转换成一个临时Complex对象
    cout<< c1.real<<","<<c1.imag <<endl;
    return 0;
}

静态成员变量与函数

  • 普通成员变量每个对象有各自的一份,而静态成员变量一共就一份,为所有对象共享。
  • 普通成员函数必须具体作用于某个对象,而静态成员函数并不具体作用于某个对象。

sizeof 不计算静态成员变量, 静态函数不可以访问非静态成员变量。

访问方法:

  1. 类名::成员名
    CRectangle::PrintTotal();
  2. 对象名.成员名
    CRectangle r; r.PrintTotal();
  3. 指针->成员名
    CRectangle*p=&r; p->PrintTotal();
  4. 引用.成员名
    CRectangle&ref=r; int n=ref.nTotalNumber;

友元

一个类的友元函数可以访问该类的私有成员, 但是友元类之间的关系,不能传递,不能继承
实现方法:

  1. 将一个类的成员函数(包括构造,析构函数)定义为另一个类的友元函数
class CCar;//提前声明CCar类,以便后面CDriver类使用
class CDriver{
pubic:
    void ModifyCar(CCar*pCar);//改装汽车
 };
class CCar{
private:
    int price;
    friend int MostExpensiveCar(CCar carsl,int total);//声明友元
    friend void CDriver:ModifyCar(CCar*pCar); //声明友元
};
  1. 将一个类定义为另一个类的友元类
class CCar{
private:
    int price;
    friend class CDrpver/声明CDriver为友元类
};
class CDriver{
public:
    CCar myCar;
    void ModifyCar(){//改装汽车
        myCar.price +=1000; //CDriver是CCar的友元类可以访问其私有成员
    }
};

静态成员变量&函数

注意静态变量&函数可以直接通过类进行调用,同时静态成员变量需要在类外*.cpp文件中进行初始化
头文件中

class chart{
public:
	static int chartCount;
	static initChartCount(){
		chartCount = 0;
	}
};

源文件中

int chart::chartCount = 0;
void test(){
	chart::initChartCount();
}

成员对象和封闭类

成员对象:一个类的成员变量是另一个类的对象
封闭类(Enclosing): 包含成员对象的类

当封闭类对象生成时

  1. 执行所有成员对象的构造函数
  2. 执行封闭类的构造函数

成员对象的构造函数调用顺序

  • 和成员对象在类中的说明(定义)顺序一致
  • 与在成员初始化列表中出现的顺序无关

当封闭类的对象消亡时

  1. 先执行封闭类的析构函数
  2. 执行成员对象的析构函数

构造函数和析构函数的调用顺序相反

派生类

class 派生类 : public 基类{}

构造函数以及析构函数调用顺序

创建派生类的对象时,执行派生类的构造函数之前:

  • 调用基类的构造函数, 初始化派生类对象中从基类继承的成员
  • 调用成员对象类的构造函数

初始化派生类对象中成员对象执行完派生类的析构函数后:

  • 调用成员对象类的析构函数
  • 调用基类的析构函数

析构函数的调用顺序与构造函数的调用顺序相反

public继承的赋值兼容规则

class base{};
class derived:public base{};
base b;
derived d;
  1. 派生类的对象可以赋值给基类对象 b=d
  2. 派生类对象可以初始化基类引用 base&br=d
  3. 派生类对象的地址可以赋值给基类指针 base*pb=&d

访问范围说明符

基类的private成员:可以被下列函数访问

  • 基类的成员函数
  • 基类的友员函数

基类的public成员:可以被下列函数访问

  • 基类的成员函数
  • 基类的友员函数
  • 派生类的成员函数
  • 派生类的友员函数
  • 其他的函数

基类的protected成员:可以被下列函数访问

  • 基类的成员函数
  • 基类的友员函数
  • 派生类的成员函数可以访问当前对象的基类的保护成员

注意:

  1. 如果在派生类中有基类一样的变量或函数,则使用域运算符进行区分

继承关系和复合关系

继承:“是”关系。

class CCircle : public CPoint {
    double r;
}
  • 基类A,B是基类A的派生类。
  • 逻辑上要求:“一个B对象也是一个A对象”。

复合:“有”关系。

class CCircle {
    double r;
    CPoint center;
}
  • 类C中“有”成员变量k,k是类D的对象,则C和D是复合关系
  • 一般逻辑上要求:“D对象是C对象的固有属性或组成部分”。

复合关系的使用

正确写法:

  1. 为“狗”类设一个“业主”类的对象指针;
  2. 为“业主”类设一个“狗”类的对象指针数组。
class CMaster;//CMaster必须提前声明,不能先写CMaster类后写Cdog类
class CDog{ 
    CMaster * pm;
};
class CMaster{
    std::vector<CDog *> dogs
}
任世事无常,勿忘初心
原文地址:https://www.cnblogs.com/FlameBlog/p/14715319.html