[英]c++ redefining types in subclasses and slicing
#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; };
為什么我對這些語義感興趣。
我要這樣做的原因是這樣的。 我有兩個類的喜劇演員,其中一個繼承人(父母)從另一個繼承人(孩子)在相同的繼承層次上集合對象。 我使用自定義容器進行聚合。 我想在父類中對容器進行typedef(typedef具有相同的名稱),並在父級的每個級別上聲明具有相同名稱的容器。
類繼承結構被設計為在較低級別上包含較少的信息(基類保留的信息最少),因此切片在這里很有意義。
編輯:
到那里,這應該清除所有問題。
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的成員感興趣的代碼提供統一的接口。
如果直接設置b::x
,則無法執行此操作。 a::x
和b::x
是兩個不同的成員,后者隱藏了前者。
您仍然可以使用static_cast<a&>(bee).x = 3
訪問類型b
的對象上的a::x
,但是基本問題是類型類型的對象上a::x
和b::x
的值b
不同步。
如果使用“屬性獲取器/設置器”對兩個x
成員的訪問進行抽象,則可以安排派生類上的setter來更新基類的成員。 或者(也許這更合適?)您可以使基類的成員protected
並直接從派生類使用它,並根據需要在從getter返回之前進行切片。
呵呵! 它有點復雜嗎?
你為什么不使用:
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;
} ;
有兩種構建軟件設計的方法: 一種方法是使其變得如此簡單,以至於顯然沒有缺陷,而另一種方法是使得它變得如此復雜以至於沒有明顯的缺陷。 第一種方法要困難得多。 CARHoare
根據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;
}
也許嘗試這樣的事情:
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));
}
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.