#include <string>
#include <iostream>
class a { public: int x;};
class b : public a {public: int x; } ;
int main()
{
b bee;
bee.x = 3;
a ay = bee;
std::cout << std::endl << ay.x << std::endl;
}
上面的代码在clang 3.0和g ++ 4.5中编译得很好。但是输出是垃圾( - 即,而不是三个)。由于编译器似乎不介意,我如何让代码行为?
其次,如果有某种方法可以使上面的切片/转换正常工作,那么如果我做了以下操作会有多糟糕,只要有充分的理由存在:
class c : public a { public: uint64_t x; };
为什么我对这些语义感兴趣。
我想这样做的原因是这个。我有两个类heirachies,其中一个heirarchy(父级)在相同的层次级别上聚合来自另一个(孩子)的对象。我使用自定义容器进行聚合。我想在父类中键入容器(typedef具有相同的名称),并声明容器在父级的每个级别处使用相同的名称。
类heirarchies旨在包含较低级别的较少信息(基类保持最少),因此切片在这里非常有意义。
修改
你去了,这应该清楚了。
class A { int x; };
class B : public A {int y;};
class Ap {std::vector<A> entries;};
class Bp : Ap{std::vector<B> entries;};
子B的成员多于子类A.但是,我不想为只对A类成员感兴趣的代码提供统一的接口。
答案 0 :(得分:2)
如果直接设置b::x
,则无法执行此操作。 a::x
和b::x
是两个不同的成员,后者隐藏了前者。
您仍然可以使用a::x
访问类型为b
的对象上的static_cast<a&>(bee).x = 3
,但基本问题是a::x
和b::x
上的值<{1}}类型的对象未同步。
如果使用“属性getter / setter”抽象对b
成员的访问权限,则可以在派生类上安排setter以更新基类的成员。或者(也许这更合适?)您可以创建基类x
的成员并直接在派生类中使用它,在从getter返回之前切换。
答案 1 :(得分:1)
你为什么不使用:
class a
{
virtual void set( int value ) { x = value; }
protected :
int x;
};
class b : public a
{
virtual void setA( int value ) { a::x = value; }
或
virtual void setA( int value ) { b::x = value; }
或
virtual void setA( int value ) { a::x = value; b::x = value; }
protected:
int x;
} ;
构建软件设计有两种方法;一种方法是使其变得如此简单以至于显然没有缺陷,另一种方法是使其变得如此复杂以至于没有明显的缺陷。第一种方法要困难得多。 C.A.R.Hoare
答案 2 :(得分:0)
根据Jon的回答,由于a :: x和b :: x是单独的变量,因此b :: x掩盖了a :: x,如果你想获得正确的语义,你需要提供一个复制转换构造函数。以下代码可以解决问题。
#include <string>
#include <iostream>
class b;
class a {
public:
a();
a(const b & bee);
int x;
};
class b : public a {public: int x; } ;
a::a() {}
a::a(const b & bee)
{
x = bee.x;
}
int main()
{
b bee;
bee.x = 3;
a ay = bee;
std::cout << std::endl << ay.x << std::endl;
}
答案 3 :(得分:0)
也许尝试这样的事情:
class A { int x; };
class B : public A {int y;};
class Ap {
public:
void Append(A *pa)
{
entries.push_back(pa);
}
A *GetA(size_t nIndex)
{
return entries.at(nIndex);
}
private:
std::vector<*A> entries;
};
class Bp : Ap
{
public:
B *GetB(size_t nIndex)
{
return dynamic_cast<B*>(GetA(nIndex));
}
};