[英]How to deal with different classes which have the same method?
例如,我有 2 個類(實際上,它更多,這就是我問這個問題的原因)使用相同的方法:
class class1{
public:
void init(){
//something
}
void dostuff(){
//something
}
//
};
class class2{
public:
void init(){
//something
}
void dostuff(){
//something
}
//
};
現在是第三個,我想以相同的方式處理這兩個類:
class upclass{
public:
upclass(class12* argclass){
myclass=argclass;
myclass->init();
}
void domorestuff(){
myclass->dostuff();
}
private:
class12* myclass; //pointer to class 1 OR class 2
};
我現在的問題是,我是否需要多個構造函數和多個聲明才能使其工作,還是有辦法解決它? 甚至可以在沒有預處理器指令的情況下使“class12”成為這些類型的空間管理員嗎?
您可以通過std::variant
顯式編寫“存儲其中之一”並通過std::visit
獲取實際類型(在需要時):
#include <variant>
using class12 = std::variant<class1*, class2*>;
class upclass {
public:
upclass(class12 argclass): myclass{argclass} {
visit([](auto classn) { classn->init(); }, myclass);
}
void domorestuff() {
visit([](auto classn) { classn->dostuff(); }, myclass);
}
private:
class12 myclass;
};
如果這些visit
過於重復,您可以考慮編寫一個漂亮的 API 來隱藏它們:
class prettyclass12: public std::variant<class1*, class2*> {
private: // both g++ and clang want variant_size<>, a quick hack:
auto& upcast() { return static_cast<std::variant<class1*, class2*>&>(*this); }
public:
using std::variant<class1*, class2*>::variant;
void init() { visit([](auto classn) { classn->init(); }, upcast()); }
void dostuff() { visit([](auto classn) { classn->dostuff(); }, upcast()); }
};
class prettyupclass {
public:
prettyupclass(prettyclass12 argclass): myclass{argclass} { myclass.init(); }
void domorestuff() { myclass.dostuff(); }
private:
prettyclass12 myclass;
};
很抱歉,這是一個廣泛的領域,確實有很多可能的解決方案。
但我想我們正在談論面向對象的編程、派生和多態函數。 您所描述的內容通常會通過 class 層次結構來解決。
您有一個帶有虛擬(多態)功能的基礎 class。
然后從這個基礎 class 派生其他類,並從基礎 class 覆蓋虛函數。
第三步,在運行時動態創建派生類的一些實例,並將新創建的類(它們的地址)存儲在指向基礎class 的指針中。
稍后,您可以通過基本 class 指針調用任何虛擬覆蓋的 function。 幕后機制將為您調用正確的 function。
此外。 您定義了一些 function init
。 這樣的 function 名稱暗示使用類構造函數。 這將按正確的順序自動調用。 首先是基礎 class 構造函數,然后是派生的 class 構造函數。
請看下面的例子:
#include <iostream>
#include <string>
class Base {
std::string baseName{};
public:
Base() { // Do initialization stuff
baseName = "Base";
std::cout << "\nConstructor Base\n";
}
virtual void doStuff() { // virtual function
std::cout << baseName << '\n';
}
};
class Derived1 : public Base {
std::string derivedName{};
public:
Derived1() : Base() { // Do initialization stuff
derivedName = "Derived1";
std::cout << "Constructor Derived1\n";
}
void doStuff() override { // Override virtaul function
std::cout << derivedName << '\n';
}
};
class Derived2 : public Base {
std::string derivedName{};
public:
Derived2() : Base() { // Do initialization stuff
derivedName = "Derived2";
std::cout << "Constructor Derived2\n\n";
}
void doStuff() override { // Override virtaul function
std::cout << derivedName << '\n';
}
};
int main() {
Base* base = new Base();
Base* derived1 = new Derived1(); // Store in base class pointer
Base* derived2 = new Derived2(); // Store in base class pointer
base->doStuff();
derived1->doStuff(); // Magic of polymorphism
derived2->doStuff(); // Magic of polymorphism
}
Base class 指針將接受從 Base 派生的所有類。
請注意。 實際上,您不應該使用原始指針,也不應該以不同的方式使用構造函數。 這只是 fotr 演示。
但是,你需要閱讀幾本關於它的書才能完全理解。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.