Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 把我对指针和引用的概念弄清楚_C++_Pointers_Polymorphism_Reference - Fatal编程技术网

C++ 把我对指针和引用的概念弄清楚

C++ 把我对指针和引用的概念弄清楚,c++,pointers,polymorphism,reference,C++,Pointers,Polymorphism,Reference,我在学校已经做了一段时间的编程工作,我正在做我的第一个独立的大型项目。我已经发现了很多我以前不知道的关于编程的东西,这非常棒 然而,我越来越觉得我不再理解C++作为一门语言,我越深入研究它。在继续之前,我想先弄清楚我对引用和指针的一些(错误)概念,如果我错了,我希望你stackoverflow能纠正我 提前谢谢,我们开始吧 1。在类之间转换时,实际转换的是虚拟表。 例如: class A{ public: A() : x(0) {}; int x; virtual voi

我在学校已经做了一段时间的编程工作,我正在做我的第一个独立的大型项目。我已经发现了很多我以前不知道的关于编程的东西,这非常棒

然而,我越来越觉得我不再理解C++作为一门语言,我越深入研究它。在继续之前,我想先弄清楚我对引用和指针的一些(错误)概念,如果我错了,我希望你stackoverflow能纠正我

提前谢谢,我们开始吧

1。在类之间转换时,实际转换的是虚拟表。

例如:

class A{
public:
    A() : x(0) {};
    int x;
    virtual void doStuff() {
        cout << x <<endl;
    }
};

class B : public A{
public:
    B() : y(1) {};
    int y;
    virtual void doStuff() {
        cout << y <<endl;
    }
};
会打印出来吗

0
0  
因为编译器会生成代码将b转换成A

3。此外,利用这种数组和STL容器多态性的唯一方法是使用指针,因为引用无法存储

由于引用是不可赋值的,所以向量不起作用,因此,如果我想拥有基类的向量,我需要创建a的指针向量,以保留B类型元素的虚拟表


对不起,如果这是TL;DR,但是当我在我的项目上做一些类设计时,这可能会困扰我一段时间,我意识到由于库接口和多态性问题,我无法真正摆脱使用指针或引用的困扰。

你说的是正确的,有必要使用指针来利用多态性。正如您所描述的,它都绑定在虚拟函数表中

在第1点中,您讨论了从类型B到A的“转换”。这有点混淆,因为更准确地说,将使用适当的组件创建一个新对象。请参见关于切片的下一点

在第2点中,您演示的是切片的原理。在这种情况下,派生类将删除派生部分,而只保留基类

需要注意的一点是,您应该在STL容器中使用boost::shared_ptr或boost::unique_ptr,否则内存管理将成为一个危险的难题


如果您没有听说过boost,您可以查看它,它是一个非常有价值的资源。

虽然您在第1点有一些好的想法,但实际上它并不是这样工作的。转换不是就地完成的,它是通过创建一个新对象来完成的,该对象复制它从转换源知道的成员(也就是说,基类成员,除非基类中有一些非常奇怪的前向声明)。派生对象的实例不会以任何方式更改。当然,副本的内存地址与原始对象不同。传递值总是涉及复制

  • 当您说“将
    b
    类型的对象
    b
    转换为
    A
    ”时,您可能指的是两件不同的事情:

    • 创建从
      b
      复制的
      a
      类型的新对象,或
    • 制作一个类型为
      a*
      的指针或一个类型为
      a&
      的引用,指向或引用
      b
    在任何一种情况下,原始对象
    b
    都不会改变。您可以在转换后将其丢弃,但这是另一个问题,并且转换本身不会改变
    b

    (除非在极少数情况下,转换运算符或所涉及的构造函数对
    B
    进行非常量引用并更改参数。但是,即使在这种情况下,它也不是您提到的vtable替换。)

    一旦创建了对象,其类型在其整个生命周期内不会改变(直到它被销毁)。这意味着,您提到的vtable替换不会发生

  • <> >是,<强> C++中的多态性是通过指针或引用实现的。>/P> 请注意,在您的示例中,a1和a2是从a和b复制的,转换不会以任何方式改变a或b

  • 是的,你说得对。或者任何类型的智能指针都是可以接受的(或者更可取)


  • 你混淆了按值传递和按引用传递

    当您按值传递时(如示例中所示),您正在从旧实例复制数据,并创建一个新实例。旧实例不会被销毁。该函数将在新实例上运行,而不会在传入的实例上运行

    当按值传递并传递派生类型时,可能会发生对象切片:

    如果确实通过引用传递,则不会创建新实例,并且该函数将在现有实例上运行。引用的类型其实并不重要,只是它限制了函数可以对对象执行的操作。它仍然在您的对象上运行,并调用您的派生实现

    对于参数而言,传递指针是按值传递(复制指针)和按引用传递(不复制指针引用的对象)的混合

    由于所有这些原因,执行多态性(在基本接口上操作,但使用派生实现)的唯一方法是通过指针或引用

    是的,STL容器不能与引用一起工作


    您可以使用来自的智能指针来绕过引用的一些限制,并绕过“愚蠢”指针的一些恶化:)

    您的实际困惑来自语句1。对象在C++中从不转换——类型的对象始终是该类型的对象(除了构造对象的基类时,一些小的场景背后的奇怪性,我们将不谈论)。相反,值会被转换,当您将一个值从一种对象类型转换为另一种对象类型时,实际发生的情况是您正在使用旧对象中的数据构建一个新对象

    在2的例子中,当调用0 0