我对C ++很陌生,我需要澄清从Java移植项目。
在Java中,我可以用这种方式声明一个基类及其派生的泛型:
public class GenericHost{
public enum HostType{
server,
client
}
public HostType type_;
}
public class MyClient extends GenericHost{
public String clientName;
}
public class MyServer extends GenericHost{
public String serverName;
}
public abstract class GenericNetwork<hostType extends GenericHost> {
public enum NetworkType{
central,
peripheral
}
private NetworkType type_;
protected hostType masterHost;
public hostType getMasterHost(){
return masterHost;
}
public abstract String getName();
}
public class CentralNetwork extends GenericNetwork<MyServer>{
@Override
public String getName(){
return masterHost.serverName;
}
}
public class PeripheralNetwork extends GenericNetwork<MyClient>{
@Override
public String getName(){
return masterHost.clientName;
}
}
这允许我:
在派生类中,我可以使用指定派生类的方法和变量(例如serverName
/ clientName
中的CentralNetwork
/ PeripheralNetwork
而不是只有基类
派生类是tiped,所以编译器/编辑器可以建议我的每个方法&amp;代码编辑期间的变量
我被迫使用派生自基类(GenericNetwork
/ GenericHost
)的类,每个错误都在编译时而不是运行时
使用泛型的每个方法/变量都将在派生类中被视为子类而不是基类(例如在CentralNetwork
中,getMasterHost
将返回派生的{{1 }},而不是基础MyServer
)。
我想知道C ++中是否存在类似内容。 我已经找到了模板,继承和子类型,但我找不到像在Java中那样更聪明的方法。我希望我错过了一些东西......
编辑: 这是我在C ++中尝试过的:
GenericHost
我现在没有C项目,所以我在飞行中重写了它,对不起任何错误......
答案 0 :(得分:0)
据我所知,没有明确的功能可以让你这样做。您可以使用static_cast
,如果类型不兼容,这将给您一个编译时错误。
template <class hostType>
class GenericNetwork {
public:
GenericNetwork() {
static_cast<GenericHost*>((hostType*)nullptr); // or 0 or NULL if not C++11
}
};
如果hostType
和GenericHost
兼容,则演员会成功但不做任何事情。否则,您将收到编译时错误。
答案 1 :(得分:0)
没有专门的功能来明确约束模板参数(*),但你可以使用(C ++ 11)
static_assert( std::is_base_of<GenericHost, hostType>::value,
"The template argument must be derived from GenericHost" );
(*)希望在C ++ 17中存在模板限制。
这是一个编译时断言,可以用作声明:
template<class hostType>
class GenericNetwork {
static_assert( std::is_base_of<GenericHost, hostType>::value,
"The template argument must be derived from GenericHost" );
public:
enum NetworkType{
central,
peripheral
}
virtual ~GenericNetwork(); // you typically want a virtual dtor in an ABC
hostType& getMasterHost(){ // you might want to return a (const) reference
return masterHost;
}
virtual std::string getName() = 0; // abstract
private:
NetworkType type_;
hostType masterHost; // or protected
// consider making the copy ctor and copy assignment op protected
// to prevent unintended slicing
}
答案 2 :(得分:0)
正如大家所指出的,C ++模板可以实现这一点,因此它不值得专用语法。
这是一个相当字面的翻译,通过简单地执行它来强制执行基类要求。
#include <string>
struct GenericHost {
enum HostType { server,client } type_;
};
template<class GenericHost=GenericHost>
struct MyClient : GenericHost { std::string clientName; };
template<class GenericHost=GenericHost>
struct MyServer : GenericHost { std::string serverName; };
template< template<class> class SpecificHost, class GenericHost=GenericHost >
struct GenericNetwork
{
typedef SpecificHost<GenericHost> hostType;
virtual ~GenericNetwork() { };
enum NetworkType { central, peripheral };
hostType getMasterHost() { return masterHost; }
virtual std::string getName() = 0;
protected: hostType masterHost;
private: NetworkType type_;
};
struct CentralNetwork : GenericNetwork<MyServer> {
std::string getName() { return masterHost.serverName; }
};
struct PeripheralNetwork : GenericNetwork<MyClient> {
std::string getName() { return masterHost.clientName; }
};
// testing: force instantiation:
struct CentralNetwork makeme;
struct PeripheralNetwork metoo;
std::string doit() { return makeme.getName() + metoo.getName(); }
我相信这会得到所有四个需求,尽管错误会在不同的地方被发现。正如其他人指出static_cast<requiredBase*>((testedClass*)0);
可以完成这项工作,但绕过保护需要工作,而不仅仅是一个错误,它会出现在类型系统中,所以我没有看到这一点。
(编辑:添加虚拟析构函数,今晚我没有甜点。坏狗。)