我有多个类,它们看起来几乎相同,作用几乎相同,但是定义和使用不同的数据,并且它们的某些功能工作不同(尽管它们具有相同的名称/签名)。
class SomeClass1{
class UniqueData1{};
UniqueData1 data;
static UniqueData1 static_data;
void doStuff1() {doWhatever( data);}
void doStuff2() {doUniqueStuff( data);}
void doUniqueStuff(UniqueData1 _data) {doABC( _data); doCDE();}
};
class SomeClass2{
class UniqueData2{};
UniqueData2 data;
static UniqueData2 static_data;
void doStuff1() {doWhatever( data);}
void doStuff2() {doUniqueStuff( data);}
void doUniqueStuff(UniqueData2 _data) {doMNO( _data); doPQR();}
};
有很多函数,如doStuff()和许多类。我如何解决此问题而无需复制粘贴?我当时在考虑模板和虚函数,但到目前为止还没有提出任何解决方案。
编辑:一些具有相同外观的功能需要调用做独特工作的功能。
嗯,很难确定您要解决的real问题是什么。但是,根据您提供的最低限度的示例,这就是使用模板的方法:
template <int I>
class SomeClass {
public:
class UniqueData{};
UniqueData data;
static UniqueData static_data;
void doStuff() { doWhatever(data); }
void doStuff2() { doUniqueStuff(data); }
void doUniqueStuff(UniqueData uniqueData);
};
void doCDE() { }
void doABC(SomeClass<1>::UniqueData) { }
void doPQR();
void doMNO(SomeClass<2>::UniqueData) { }
template<>
void::SomeClass<1>::doUniqueStuff(SomeClass<1>::UniqueData data) {
doABC(data);
doCDE();
}
template<>
void::SomeClass<2>::doUniqueStuff(SomeClass<2>::UniqueData data) {
doMNO(data);
doPQR();
}
int main() {
SomeClass<1>().doStuff2();
SomeClass<2>().doStuff2();
}
这里,模板实例具有其自己的唯一数据类型和两个功能。这两个函数专用于调用不同的函数。
编辑:您指定要UniqueData
具有一些唯一成员。如果您愿意灵活,可以使用元组:
#include <functional>
#include <iostream>
#include <tuple>
#include <string>
template<typename T>
void doWhatever(T) { }
// This is now a variadic template. All arguments after id are packed into TUniqueDataMembers
template <int id, typename... TUniqueDataMembers>
class SomeClass {
public:
// UnqiueData has a tuple member (with TUniqueDataMembers). It has one member of each template argument given
class UniqueData {
public:
UniqueData() : data(std::make_tuple(TUniqueDataMembers{}...)) { }
std::tuple<TUniqueDataMembers...> data;
};
UniqueData data;
static UniqueData static_data;
void doStuff() { doWhatever(data); }
void doStuff2() { doUniqueStuff(data); }
void doUniqueStuff(UniqueData uniqueData);
};
// Using a type definition saves some boilerplate, now that we're using multiple template arguments
using SomeClass1 = SomeClass<1, int>;
using SomeClass2 = SomeClass<2, double, std::string>;
void doCDE() { }
void doABC(SomeClass1::UniqueData data) {
// Use std::get<index>(tuple) to access unique data
std::cout << "int: " << std::get<0>(data.data) << "\n";
}
void doPQR() { }
void doMNO(SomeClass2::UniqueData data) {
std::cout << "double: " << std::get<0>(data.data) << "\n";
std::cout << "string: " << std::get<1>(data.data) << "\n";
}
template<>
void SomeClass1::doUniqueStuff(SomeClass1::UniqueData data) {
doABC(data);
doCDE();
}
template<>
void SomeClass2::doUniqueStuff(SomeClass2::UniqueData data) {
doMNO(data);
doPQR();
}
int main() {
SomeClass1 class1 {};
std::get<0>(class1.data.data) = 42;
class1.doStuff2();
SomeClass2 class2 {};
std::get<0>(class2.data.data) = 2.5;
std::get<1>(class2.data.data) = "hello, world!";
class2.doStuff2();
}