JHHK

欢迎来到我的个人网站
行者常至 为者常成

13、匿名对象、默认构造函数、隐式构造、内部类、局部类

目录

对象类型的参数和返回值

//使用对象类型作为函数的参数或者返回值,可能会产生一些不必要的中间对象
class Car{
private:
public:
    int m_price;
    Car(int price = 0):m_price(price){
        cout << "Car(int) - " << this << " - " << this->m_price << endl;
    }
    
    Car(const Car &car):m_price(car.m_price){
        cout << "Car(const Car &) - " << this << " - " << this->m_price << endl;
    }
    
    ~Car(){
        cout<<"~Car() - "<<this<<endl;
    }
};


// !!!:对象类型作为参数
void carTest(Car car){
    //相当于 Car car = 传进来的car 调用的拷贝构造函数 产生了临时对象
    //函数调用结束临时对象销毁
    //产生了额外的栈开销影响性能
}
void tempObjectUsing(){
    //Car(int) - 0x7ffeefbff5a8 - 100
    Car car(100);
    
    
    //产生了一个额外的临时对象
    //Car(const Car &) - 0x7ffeefbff5a0 - 100
    carTest(car);
}


// !!!:对象类型作为返回值
//课程讲解时对象作为返回值也会产生调用拷贝构造函数产生临时对象
//但在xcode下并未产生不知道是否是编译器做了优化?????
//见图解:13_1对象做参数或返回值.png
Car carTest1(){
    Car car(200);
    return car;
}
void tempObjectUsing1(){
    Car car1 = carTest1();//
    cout<<"-----------------"<<endl;
    
    Car car3(300);
    car3 = carTest1();
    cout<<"-----------------"<<endl;
}


// !!!:引用作为参数、返回值
//使用引用就不会产生临时对象,减少调用开销
Car & carTest2(Car & car){
    return car;
}
void tempObjectUsing2(){
    Car car(400);
    Car& car4 = carTest2(car);
}

匿名对象(临时对象)

匿名对象:没有变量名、没有被指针指向的对象,用完后马上调用析构

class Person {
public:
    Person() {
        cout << "Person() - " << this << endl;
    }
    Person(const Person &person) {
        cout << "Person(const Person &person) - " << this << endl;
    }
    ~Person() {
        cout << "~Person() - " << this << endl;
    }
    void display() {
        cout << "display()"  << endl;
    }
};

void test1(Person person) {

}

Person test2() {
    // Person person;
    return Person();
}

void anonymityObject(){

    Person person;
    cout<<"-----------------1-----------------"<<endl;
    
    Person();
    cout<<"-----------------2-----------------"<<endl;
   
    test1(person);
    cout<<"-----------------3-----------------"<<endl;
    
    test2();
    cout<<"-----------------4-----------------"<<endl;
}

隐式构造

C++中存在隐式构造的现象:某些情况下,会隐式调用单参数的构造函数 可以通过关键字explicit禁止掉隐式构造

class Truck{
private:
    int m_price;
public:
    Truck(int price = 0):m_price(price){
        cout<<"Truck(int price)"<<endl;
    }
    
    //可以通过关键字explicit禁止掉隐式构造
//    explicit Truck(int price = 0):m_price(price){
//        cout<<"Truck(int price)"<<endl;
//    }

    ~Truck(){
        cout<<"~Truck()"<<endl;
    }
};


void implicitConstrutor(){
    Truck tru = 30;
}

默认构造函数

编译器自动生成的构造函数
C++的编译器在某些特定的情况下,会给类自动生成无参的构造函数,比如
成员变量在声明的同时进行了初始化
有定义虚函数
虚继承了其他类
包含了对象类型的成员,且这个成员有构造函数(编译器生成或自定义)
父类有构造函数(编译器生成或自定义)

总结一下
对象创建后,需要做一些额外操作时(比如内存操作、函数调用),编译器一般都会为其自动生成无参的构造函数

友元

友元包括友元函数和友元类
如果将函数A(非成员函数)声明为类C的友元函数,那么函数A就能直接访问类C对象的所有成员
如果将类A声明为类C的友元类,那么类A的所有成员函数都能直接访问类C对象的所有成员
友元破坏了面向对象的封装性,但在某些频繁访问成员变量的地方可以提高性能

class Point {
     friend Point add(const Point &, const Point &);
    friend class Math;
private:
    int m_x;
    int m_y;
public:
    int getX() const { return this->m_x; };
    int getY() const { return this->m_y; };
    Point(int x, int y) :m_x(x), m_y(y) { }
};

class Math {
public:
    Point add(const Point &point1, const Point &point2) {
        return Point(point1.m_x + point2.m_x, point1.m_y + point2.m_y);
    }
};

Point add(const Point &point1, const Point &point2) {
    return Point(point1.m_x + point2.m_x, point1.m_y + point2.m_y);
}

void friendsUsing(){
    Point point1(10, 20);
    Point point2(20, 30);
    Point point = add(point1, point2);
}

内部类

如果将类A定义在类C的内部,那么类A就是一个内部类(嵌套类)
内部类的特点
支持public、protected、private权限
成员函数可以直接访问其外部类对象的所有成员(反过来则不行)
成员函数可以直接不带类名、对象名访问其外部类的static成员
不会影响外部类的内存布局
可以在外部类内部声明,在外部类外面进行定义

// Person
class PersonSix {
private:
    static int ms_legs;
    static void other() {}

    int m_age;
    void walk() {}

public:
    class Car {
        int m_price;
    public:
        Car() {
            cout << "Car()" << endl;
        }
        
        void run() {
            PersonSix person;
            person.m_age = 10;
            person.walk();
            
            ms_legs = 10;
            other();
        }
    };
    
    PersonSix() {
        cout << "PersonSix()" << endl;
        Car car;
    } 
};

int PersonSix::ms_legs = 2;

class PointSix {
    class Math {
        void test();
    };
};

void PointSix::Math::test() {}

void inClassUsing(){
    cout << sizeof(PersonSix) << endl;
    PersonSix person;
    PersonSix::Car car;
}

局部类

在一个函数内部定义的类,称为局部类 局部类的特点 作用域仅限于所在的函数内部 其所有的成员必须定义在类内部,不允许定义static成员变量 成员函数不能直接访问函数的局部变量(static变量除外)

int g_age = 20;

void test() {
    int age = 10;
    static int s_age = 30;

    // 局部类
    class Person {
    public:
        static void run() {
            g_age = 30;
            s_age = 40;

            cout << "run()" << endl;
        }
    };

    Person person;
    Person::run();
}

行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.