记一次编译错误

我在照着STL 源码刨析写 STL 的时候出现了一个编译错误. 当时的情况是我要用一个派生类的指针给一个基类指针的引用赋值, 类似于:

class Base {};
class Derived : public Base {};

Derived *d = new Derived();
Base *&b = d;

但是编译器报错, 错误信息类似于:

error: cannot bind non-const lvalue reference of type ‘Base*&’ to an rvalue of type ‘Base*’

在 C++ 中, 派生类的指针可以直接给基类指针赋值以实现多态的特性. 但是却不可以给基类指针的引用赋值. 这个报错当时令我很困惑. 经过查阅并分析报错信息, 该语句的执行过程应该是首先创建了一个类型为 Base* 的临时值, 用 d 来初始化, 再把这个临时值赋予变量 b. 因为这个临时值是右值不能给左值赋值, 所有会有这个报错.

这个问题可以用两种方式解决.

第一种方式是通过常量引用可以指向右值实现的. 就是把变量 b 声明为常量指针, 即 Base * const &b = d, 这样就解决了这个问题.

但是在我当时的代码中不能通过这个方法解决. 因为报错的函数是红黑树的一个迭代函数, 有可能改变 d 的值. 这样的解决方法会复制 d 的值, 使得函数内改变的局部值无法作用到外部的 d 上.

第二种方式是先把 d 做一个强制类型转换再赋值给 b, 即 Base *&b = (Base*&)d. 这样就可以在函数中通过修改 b 的值修改 d.

下面是一个示例代码. 验证两种方法.

class Base {};
class Derived : public Base {};

Derived *pd = new Derived();
Base * const &pb1 = pd;   // 方法 1
Base *&pb2 = (Base*&)pd;  // 方法 2

cout << "addr of pd:\t" << &pd << endl;
cout << "addr of pb1:\t" << &pb1 << endl;
cout << "addr of pb2:\t" << &pb2 << endl;

编译没有报错, 运行得到下面的结果:

add of pd:	0x7ffcdec09978
add of pb1:	0x7ffcdec09980
add of pb2:	0x7ffcdec09978

说明方法 1 创建了一个新的指针, 而方法 2 绑定在原来的指针上.

posted @   谋杀肚腩  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
点击右上角即可分享
微信分享提示