从派生类构造函数向基类构造函数传递引用的问题
C++基类持有外部结构体引用的问题与解决
问题描述
希望在Derived类的初始化列表中让Base类持有Coord结构体的引用,但传递Coord实例给Derived构造函数时,会创建新的Coord实例——无法从派生类更新外部的coord对象。请问这种传递引用的方式是否违规,还是做法有误?
示例代码
#include <iostream> struct Coord{ int x = 1; int y = 1; void printCoord(){ std::cout << "X: " << x << " Y: " << y << std::endl; } }; class Base{ public: Coord myCoord; Base(Coord &coord): myCoord(coord){} // How do I modify this line so Base gets a copy of myCoord? virtual void updateCoord(int x, int y){}; }; class Derived : public Base { public: Derived(Coord &coord): Base(coord){} // Or possibly this line? virtual void updateCoord(int x, int y){ myCoord.x = x; myCoord.y = y; std::cout << "Updated to:" << std::endl; myCoord.printCoord(); } }; int main(){ Coord myCoord; Base *baseptr; Derived d(myCoord); baseptr = &d; std::cout << "Before update:" << std::endl; myCoord.printCoord(); baseptr->updateCoord(2,2); std::cout << "After update:" << std::endl; myCoord.printCoord(); return 0; }
预期输出
Before update: X: 1 Y: 1 Updated to: X: 2 Y: 2 After update: X: 2 Y: 2
实际输出
Before update: X: 1 Y: 1 Updated to: X: 2 Y: 2 After update: X: 1 Y: 1
问题根源与解决方法
问题原因
Base类中的myCoord是成员对象而非引用,构造函数初始化列表中的myCoord(coord)执行的是拷贝构造操作——将传入的外部Coord实例复制了一份存储在Base内部。后续Derived类的updateCoord修改的是这份内部拷贝,自然不会影响外部的Coord对象。
修正方案
将Base类中的myCoord改为引用类型,让它绑定到外部传入的Coord实例,而非创建拷贝:
修改后的完整代码
#include <iostream> struct Coord{ int x = 1; int y = 1; void printCoord(){ std::cout << "X: " << x << " Y: " << y << std::endl; } }; class Base{ public: Coord& myCoord; // 修改为引用类型 // 初始化列表绑定传入的引用 Base(Coord &coord): myCoord(coord){} virtual void updateCoord(int x, int y){}; }; class Derived : public Base { public: Derived(Coord &coord): Base(coord){} virtual void updateCoord(int x, int y){ myCoord.x = x; myCoord.y = y; std::cout << "Updated to:" << std::endl; myCoord.printCoord(); } }; int main(){ Coord myCoord; Base *baseptr; Derived d(myCoord); baseptr = &d; std::cout << "Before update:" << std::endl; myCoord.printCoord(); baseptr->updateCoord(2,2); std::cout << "After update:" << std::endl; myCoord.printCoord(); return 0; }
关键说明
- 引用成员的初始化:C++中引用成员必须在构造函数的初始化列表中完成绑定,不能在构造函数体内赋值,所以Base的构造函数必须用
myCoord(coord)来绑定外部传入的Coord引用。 - 生命周期注意事项:必须保证外部的Coord对象(如main中的
myCoord)的生命周期长于Base/Derived对象,否则会出现悬空引用问题,导致未定义行为。
修改后运行代码,实际输出将与预期一致。
内容的提问来源于stack exchange,提问作者BooleanSmith
相关产品推荐
相关产品推荐

