簡體   English   中英

子類和切片中的c ++重新定義類型

[英]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::xb::x是兩個不同的成員,后者隱藏了前者。

您仍然可以使用static_cast<a&>(bee).x = 3訪問類型b的對象上的a::x ,但是基本問題是類型類型的對象上a::xb::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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM