zoukankan      html  css  js  c++  java
  • [C++]对象初始化 / 构造函数

    最好不要将对象设为static duration的(静态的、全局的),这样的话,对象的初始化顺序以及销毁顺序均不可控,多线程时可能出现问题。

    构造函数:

    构造函数可能会调用内部函数,如果这个函数是虚函数,可能出现问题(其实也不是啥问题,如果熟悉派生类的构造过程的话)。详见下例:

    构造函数不会重载virtual
    #include <iostream>
    using std::cout;
    using std::endl;
    
    class Base
    {
    public:
        virtual void Foo(){ cout << "执行了Base的Foo()函数" << endl; }
        Base()
        {
            cout << "执行了Base的构造函数并开始调用Foo()" << endl;
            Foo();
        }
        void Func()
        {
            cout << "执行了Base的Func()函数并开始调用Foo()" << endl;
            Foo();
        }
    };
    class Derive : public Base
    {
    public:
        virtual void Foo(){ cout << "执行了Derive中的Foo()函数" << endl; }
    };
    
    void main()
    {
        cout << "创建Derive的实例。构造时执行Base的Foo()函数" << endl;
        Derive obj;
        cout << endl;
        cout << "Derive实例创建后,基类的Func()执行Derive的Foo()函数" << endl;
        obj.Func();
        cout << endl;
        cout << "改变其类型为Base后,基类的Func()执行Base的Foo()函数←这是virtual的特性" << endl;
        Base obj_base = (Base)obj;  
        obj_base.Func();
        
        cout << endl << "改变指针的类型不会改变Foo()的选择,必须强制类型转换" << endl;
        cout << "原因是强制类型转换生成了新的对象起始地址" << endl;
        cout << "Derive对象的地址:"<< &obj << " ~ " << &obj + sizeof(Derive) << endl;
        cout << "Base  对象的地址:"<< &obj_base << " ~ " << &obj_base + sizeof(Base) << endl;
        system("pause");
    }

    结果:

    创建Derive的实例。构造时执行Base的Foo()函数
    执行了Base的构造函数并开始调用Foo()
    执行了Base的Foo()函数

    Derive实例创建后,基类的Func()执行Derive的Foo()函数
    执行了Base的Func()函数并开始调用Foo()
    执行了Derive中的Foo()函数

    改变其类型为Base后,基类的Func()执行Base的Foo()函数←这是virtual的特性
    执行了Base的Func()函数并开始调用Foo()
    执行了Base的Foo()函数

    改变指针的类型不会改变Foo()的选择,必须强制类型转换
    原因是强制类型转换生成了新的对象起始地址
    Derive对象的地址:003CFA10 ~ 003CFA20
    Base  对象的地址:003CFA04 ~ 003CFA14
    请按任意键继续. . .

    创建对象的数组时会执行默认构造函数。

    默认构造函数

    默认构造函数执行那些无逻辑意义的初始化(比如int置为0,枚举置为NULL等等),对于有逻辑意义的初始化,放在Init()函数中进行。

    对于Interface,尽量不指定构造函数。如果要定义构造函数,也只定义默认构造函数。并且,将默认构造函数置为protected。这样既防止了创建Interface的实例,又可以在实现接口时调用构造函数。

    public:实例课访问,成员函数可访问。public派生类实例可访问,成员函数可访问。

    protected:实例不可访问,成员函数可访问。public派生类实例不可访问,成员函数可访问。

    private:实例不可访问,成员函数可访问。public派生类实例不可访问,成员函数不可访问。

    只有一个参数的构造函数:

    只有一个参数的构造函数会被认为是implicit,即隐式转换函数。它除了构造函数的功能外,还具有隐式转换的功能。
    这样子的特性不太好,所以最好显式声明为explicit,禁用隐式转换。

    比起其他的单参数构造函数,拷贝构造函数更加应该引起重视:因为它会被默认隐式创建。最好也禁用之——使用private定义。
    同时记得禁用赋值——将operator=(Type)也置为private。

  • 相关阅读:
    NCNN优化实时面部关键点检测
    使用 div 标签 contenteditable="true" 实现一个 聊天框,支持 Ctrl + v 粘贴图片
    《精益创业》读书总结
    DATAX使用
    canal增量同步原理以及使用说明
    element rules required 自定义表达式
    JavaScript 数组映射,重新整理
    wangeditor遮挡其他控件
    多个axios按顺序执行
    .NET Core 中基于 IHostedService 实现后台定时任务
  • 原文地址:https://www.cnblogs.com/SelaSelah/p/2439523.html
Copyright © 2011-2022 走看看