2013-05-15 148 views
2

是否有派生類的任何主流語言的設計模式繼承代碼從基類並評估派生類的範圍中的代碼?例如(使用僞C++語法):繼承:評估派生類的範圍?

class Base { 
    // (How) can this be modified to be evaluated 
    // in the derived class's scope so that it 
    // prints the size of the derived class? 
    void printSize() { 
     cout << sizeof(*this) << endl; 
    } 
}; 

class Derived : public Base { 
    void* dummy; 
}; 

int main() { 
    Base base; 
    Derived derived; 
    base.printSize(); 
    derived.printSize(); // Should be > base.printSize(). 
    return 0; 
} 

我意識到這可以用宏來完成,但需要宏在派生類的範圍被明確實例化。

編輯:爲了澄清,這篇文章的整點是,我不想手動重新實現在每一個派生類相似printSize()或任何東西。我正在尋找一個巧妙的模式來編譯器/解釋器(即使我在我的例子中使用C++,我也很想知道任何語言是否有解決方案)爲我做這件事。

編輯2:我想這在動態語言中很簡單。我是靜態類型語言,大多數是C++,Java和D.

編輯#3更感興趣的是解決方案:模式應在運行時類型,而不是編譯時類型的工作。因此,D模板這個參數不是解決方案。

+0

你是什麼意思評估?在你給它看起來像正常繼承的情況下 – greedybuddha

+0

printSize()將始終打印基類的大小,因爲它在Base的範圍內編譯一次。我希望它打印派生類的大小,如果它在Derived的實例上調用。 – dsimcha

+0

這隻適用於C++語言。當然,使用java和正確的java語法,這會自動被認爲是虛擬的,並且會打印派生類的大小 – greedybuddha

回答

1

在C++中,我想你會得到越接近是奇異遞歸模板模式(CRTP),但它有嚴重的侷限性:

template<typename T> 
class Base { 
    void printSize() { 
     std::cout << sizeof(T) << std::endl; 
    } 
    void doSomething() { 
     T::member_variable = 3; 
     T::doSomethingElse(); 
    } 
}; 

class Derived : public Base<Derived> { 
public: 
    int member_variable; 
    void doSomethingElse() { ... } 
}; 

你也可以使用虛擬的方法,但它們需要你要在每個派生類中重新實現該方法,所以我猜這不是你想要的。

要真正實現您的想法,您可能需要動態語言(例如Python)。沒有保證,但這是一個不尋常的「功能要求」,我不知道動態語言很好......

2

如果是「主流」,你包括主流腳本語言,如Perl或Python,那麼是的。由於Perl的「對象」通常是哈希映射,並且繼承樹的所有級別的所有變量都在同一個「範圍」中(即,進入相同的散列圖)。 Python類有類似的情況發生,儘管(IIRC)Python有一種方法可以創建一個符號,這個符號會被破壞,這樣它就會根據代碼寫入的類來區分。當然,這兩種語言都沒有「sizeof 「概念本身,所以你的具體例子不會特別相關。

在C++中,根據您的示例調用的類型爲成員函數決定當前類的概念並沒有(據我所知)確實有效。但是,您可能能夠接近您使用模板描述的內容。例如,像這樣:

template<typename T> 
void printSize(T &t) { 
    cout << sizeof(t) << endl; 
} 
int main() { 
    Base base; 
    Derived derived; 
    printSize(base); 
    printSize(derived); 
} 

(旁註:在C++中,因爲你Base是空的,實際上不能保證sizeof(Base)>sizeof(Derived) ---空基地優化可能是一個正常的Base採用這樣(可能)是一個指針的大小,但DerivedBase部分實際上是空的,大多數平臺可能會爲這樣的空類分配1個字節,指針通常比這個大,但沒有指定。)

+0

+1關於Perl/Python「內部」​​的解釋。 :) – syam

2

D來救援。 Template mixins正是用於在目標範圍內被評估的工具,你不需要任何特殊類型的層次結構(您仍然可以添加一個,如果你想當然):

http://dpaste.1azy.net/eec411e8

mixin template SizePrinter() 
{ 
    static void printSize() 
    { 
     import std.stdio; 
     writeln(__traits(classInstanceSize, typeof(this))); 
    } 
} 

class Tested1 
{ 
    int[64] dummy; 
    mixin SizePrinter; 
} 

class Tested2 
{ 
    int[16] dummy; 
    mixin SizePrinter; 
} 

void main() 
{ 
    Tested1.printSize(); 
    Tested2.printSize(); 
} 

應用的輸出:

272 
80 
+0

我知道D中的模板mixin。這是一個比C++提供的更好的解決方案,但它仍然需要明確地在派生類中完成某些操作,即使它是單線程,也可能會令人討厭。 – dsimcha

+0

啊,dsimcha,對不起,我沒有注意到它被D社區的人問過。你用RTTI方法很好嗎? –

+0

RTTI可以解決希望獲得課程大小的特定情況下的問題,但這不是一個通用的解決方案。 – dsimcha

1

在D中有一個更好的解決方案,使用Template This Parameter

代碼:http://dpaste.1azy.net/78810a79

import std.stdio; 

class Base { 
    int[64] dummy1; 
    final static size_t getSize(this T)() { 
    return __traits(classInstanceSize, T); 
    } 
} 

class Derived : Base { 
    int[16] dummy2; 
} 

void main() { 
    writeln(Base.getSize()); // prints: 272 
    writeln(Derived.getSize()); // prints: 336 
} 

編輯:行動,這隻會爲靜態式工作。不是解決您的問題。