C++ 把我对指针和引用的概念弄清楚
我在学校已经做了一段时间的编程工作,我正在做我的第一个独立的大型项目。我已经发现了很多我以前不知道的关于编程的东西,这非常棒 然而,我越来越觉得我不再理解C++作为一门语言,我越深入研究它。在继续之前,我想先弄清楚我对引用和指针的一些(错误)概念,如果我错了,我希望你stackoverflow能纠正我 提前谢谢,我们开始吧 1。在类之间转换时,实际转换的是虚拟表。 例如:C++ 把我对指针和引用的概念弄清楚,c++,pointers,polymorphism,reference,C++,Pointers,Polymorphism,Reference,我在学校已经做了一段时间的编程工作,我正在做我的第一个独立的大型项目。我已经发现了很多我以前不知道的关于编程的东西,这非常棒 然而,我越来越觉得我不再理解C++作为一门语言,我越深入研究它。在继续之前,我想先弄清楚我对引用和指针的一些(错误)概念,如果我错了,我希望你stackoverflow能纠正我 提前谢谢,我们开始吧 1。在类之间转换时,实际转换的是虚拟表。 例如: class A{ public: A() : x(0) {}; int x; virtual voi
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替换不会发生你混淆了按值传递和按引用传递 当您按值传递时(如示例中所示),您正在从旧实例复制数据,并创建一个新实例。旧实例不会被销毁。该函数将在新实例上运行,而不会在传入的实例上运行 当按值传递并传递派生类型时,可能会发生对象切片: 如果确实通过引用传递,则不会创建新实例,并且该函数将在现有实例上运行。引用的类型其实并不重要,只是它限制了函数可以对对象执行的操作。它仍然在您的对象上运行,并调用您的派生实现 对于参数而言,传递指针是按值传递(复制指针)和按引用传递(不复制指针引用的对象)的混合 由于所有这些原因,执行多态性(在基本接口上操作,但使用派生实现)的唯一方法是通过指针或引用 是的,STL容器不能与引用一起工作
您可以使用来自的智能指针来绕过引用的一些限制,并绕过“愚蠢”指针的一些恶化:)您的实际困惑来自语句1。对象在C++中从不转换——类型的对象始终是该类型的对象(除了构造对象的基类时,一些小的场景背后的奇怪性,我们将不谈论)。相反,值会被转换,当您将一个值从一种对象类型转换为另一种对象类型时,实际发生的情况是您正在使用旧对象中的数据构建一个新对象 在2的例子中,当调用
0
0