在c ++中实例化对象有多少种方法?它们之间有什么区别

时间:2018-03-24 16:02:50

标签: c++ initialization

当我来到c ++时,我是一个新手,当我研究虚拟函数和纯虚函数时,我发现它与以不同方式实例化对象的方式不同。这让我很困惑。如果你能提供帮助,我将不胜感激。以下是代码和输出。

#include <iostream>

using namespace std;

class A {
public:
    int va;
    int vb;

    virtual void m1() {
        cout << "this is A's m1() method" << endl;
    }

    void m3() {
        cout << "this is A's m3() method" << endl;
    }
};

class B : public A {
public:
    void m1() {
        cout << "this is B's m1() method" << endl;
    }

    void m2() {
        cout << "this is B's m2() method" << endl;
    }

    void m3() {
        cout << "this is B's m3() method" << endl;
    }
};

int main() {
    cout << "start" << endl;
    A a1 = B();
    a1.m1();
    a1.m3();
    cout << "===================" << endl;
    A *a2;
    a2 = new B();
    a2->m1();
    a2->m3();
    delete[]a2;
    /*
        output:
        this is A's m1() method
        this is A's m3() method
        ===================
        this is B's m1() method
        this is A's m3() method
    */
    return 0;
}

我想知道A a1 = B();A *a2; a2 = new B();之间的区别。感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

我想知道A a1 = B();A *a2; a2 = new B();之间的区别。

A a1 = B();会将B临时切片到A堆栈变量。 B的任何其他成员变量或行为都将被丢弃。 A堆栈变量a1将在范围的末尾被破坏。

A *a2; a2 = new B();将有一个指针指向全局存储分配的B对象。 a2变量将指向该B对象,该对象仍然是B对象。在B中重写的A的虚拟方法将使用B方法。 A的非虚方法可通过A指针访问,但除非使用强制转换,否则无法访问B(虚拟或非虚拟)的其他方法。

delete[]a2;是未定义的行为,在我的机器上会使应用程序崩溃。由于B对象是使用new B()在全局商店中分配的,因此应使用delete a2;删除它。

答案 1 :(得分:0)

你碰巧知道/学习Java吗?在C ++中,事情有点不同。

A a1A类型的对象,无论您如何构造它。特别是:

A a1 = B();

以下内容:

  • 创建B
  • 类型的临时对象
  • 使用内置的复制构造函数创建类型为a1的对象A。它会临时内容复制到a1。只会复制临时的A部分。
  • 临时B对象被销毁。

这就是为什么a1上的所有方法都是真正的A方法。没有虚拟机制会达到B的方法,因为a1不是B类型的对象。

另一方面,

A* a2是指向A或派生类型的任何对象的指针。它只是一个指针,它本身并不代表一个对象。

现在,当您为其指定new B()时,它将指向实际类型B的对象。通过这个指针调用虚方法将达到B的方法,就像你预期的那样。

顺便说一句。通过指针引用的单个对象应通过delete a2删除。如果您有数组,则使用delete [] a2