我有两个类似结构的类。
class A{
int a;
char *b;
float c;
A(char *str) { //allocate mem and assign to b }
};
class B{
int a;
char *b;
float c;
B(char *str) { //allocate mem and assign to b }
B(B & bref) { //properly copies all the data }
};
我想将B
的对象复制到A
的对象。以下转换是否正常?
A aobj("aobjstr");
B bobj("bobjstr");
bobj = aobj; //case 1
bobj = B(aobj); //case 2
案例2会起作用吗?当调用B的复制构造函数时,aobj
是否会被正确转换并解释为B &
?
编辑:怎么样?
B bobj(aobj)
答案 0 :(得分:2)
不,如果不编写转换构造函数或转换运算符,则无法在不相关的类型之间进行隐式转换。据推测,你的编译器告诉你这个;我的错误如下:
error: no match for ‘operator=’ in ‘bobj = aobj’
note: no known conversion for argument 1 from ‘A’ to ‘const B&’
error: no matching function for call to ‘B::B(A&)’
您可以通过向B
提供转换构造函数来允许转换:
class B {
// ...
B(A const & a) { /* properly copy the data */ }
};
如果你不能改变类,那么你需要一个非成员函数来进行转换;但这可能只有在班级成员公开的情况下才有可能。在您的示例中,所有成员(包括构造函数)都是私有的,因此根本不能使用这些类。据推测,在您的真实代码中并非如此。
如果你想生活危险,你可能会明确地将A
对象重新解释为B
,因为它们都是具有相同数据成员的标准布局类型: / p>
// DANGER: this will break if the layout of either class changes
bobj = reinterpret_cast<B const &>(a);
请注意,由于您的类分配内存,因此可能需要在其析构函数中释放它;为避免双重删除,您还必须按照Rule of Three正确实现复制构造函数和复制赋值运算符。
如果这听起来太多了,为什么不使用std::string
来处理内存管理呢?
答案 1 :(得分:2)
如果您尝试编译它,您会发现这些都不起作用。首先,你的构造函数是private
。
bobj = aobj; //case 1
这会尝试使用签名调用赋值运算符:
B& B::operator =(A const&)
这不存在,编译将失败。
bobj = B(aobj); //case 2
这会尝试调用A::operator B()
,它不存在,编译将失败。
最后:
B bobj(aobj)
这会尝试调用带有签名B::B(A const&)
的构造函数,该签名不存在,编译将失败。
你说,
我无法更改/修改A类和B类,这些都是生成的。
然后需要修复生成器,或者你必须编写自己的适配器。
答案 2 :(得分:0)
您可以通过考虑以下注释来完成此操作:
1) char* b
出现问题。当您将aobj复制到bobj时,指针aobj.b
的值将被复制到bobj.b
,这意味着它们都引用相同的内存位置并更改为:aobj.b[0] = 'Z'
将导致bobj.b
{1}}要改变。
您可以通过将b
从指针更改为平面数组来解决此问题:
//...
char b[MAXLEN];
//...
更好的解决方案是定义一个构造函数(接受另一种类型)并重载赋值(=)运算符,至少对于类B,并处理指针赋值(为新指针分配缓冲区并将内容复制到它)。
2)更新:示例语法如下:
bobj = B(reinterpret_cast<B&> (aobj));
// or simply:
bobj = reinterpret_cast<B&> (aobj);
3)请注意,这是危险的,不安全,不推荐。这意味着您的解决方案的设计可能会发生变化。例如,A和B都可以从公共基类继承; B继承自A;或者B明确定义了A类的构造函数和赋值运算符。这些更值得推荐。