代码之家  ›  专栏  ›  技术社区  ›  Chui Tey

嘲笑复制构造函数的C++类

c++
  •  0
  • Chui Tey  · 技术社区  · 4 年前

    我从C++到C++,当我尝试构造测试时,复制构造函数让我很难模仿我习惯的方式。

    #include <iostream>
    
    using namespace std;
    
    class DB {
    public:
        virtual int getValue() { return 42; }
        DB(const DB& source) { }
        DB() { }
    };
    
    class DB_Mock: public DB {
    public:
        virtual int getValue() { return 999; }
    };
    
    class A {
    public:
        A(DB db) {
            m_db = db;
        }
        void doIt() {
            cout << "Result:" << m_db.getValue() << endl;
        }
    private:
        DB m_db;
    };
    
    int main() {
        /* prints 42 as expected */
        DB db;
        A a(db);
        a.doIt();
    
        /* prints 42, expected 999 */
        DB_Mock db_mock;
        A a2(db_mock);
        a2.doIt();
        return 0;
    }
    
    

    你如何处理这样的问题?

    1 回复  |  直到 4 年前
        1
  •  2
  •   srilakshmikanthanp    4 年前

    m_db不是一个引用或指针,c++多态性只与基类指针或引用一起工作。

        A(DB db) {
            m_db = db; // m_db just sliced copy of base part of db.
        }
    

    将此更改为引用

    class A
    {
    public:
        explicit A(DB &db) : m_db(db) // it is initializing not copy
        {
        }
        void doIt()
        {
            std::cout << "Result:" << m_db.getValue() << std::endl;
        }
    
    private:
        DB &m_db;  // Now m_db is reference
    };
    

    Compile and Run Here

    1. Constructors and member initializer lists
    2. Smart pointer
    3. override
    4. 看到了吗 virtual table 要了解vu ptr

    编辑:

    作为 Pete Becker

    A make()
    {
        DB db;
        A a(db);
        return a;
    }
    
    int main()
    {
       const A &a = make();
       // Wrong db is destroyed (dangling reference).
       a.doIt(); // assume doIt(), getValue() are declared as const
       return 0;
    }
    

    上面的代码是错误的(未定义的行为),所以我建议使用智能指针(堆存储)来避免这个问题。

    谢谢。