0

我对 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;
    }
}

这使我能够:

  1. 在派生类中,我可以使用指定派生类的方法和变量(例如serverName/ clientNamein CentralNetwork/ PeripheralNetwork),而不仅仅是基类的

  2. 派生类是倾斜的,因此编译器/编辑器可以在代码编辑期间向我建议每个方法和变量

  3. 我被迫使用从基类(GenericNetwork/ GenericHost)派生的类,每个错误都在编译时而不是运行时

  4. 每个使用泛型的方法/变量都将在派生类中被视为子类而不是基类(例如,在 中CentralNetworkgetMasterHost将返回派生类,而MyServer不是基类GenericHost)。

我想知道 C++ 中是否存在类似的东西。我已经在寻找模板、继承和子类型,但是我找不到像在 Java 中那样做更聪明的事情的方法。我希望我错过了什么...

编辑:这是我在 C++ 中尝试的:

class GenericHost{
    public enum HostType{
        server,
        client
    }
    public HostType type_;
}

class MyClient : public GenericHost{
    public String clientName;
}

class MyServer : public GenericHost{
    public String serverName;
}

template<class hostType : GenericHost>             <--WISH, forced base class
class GenericNetwork {
    public enum NetworkType{
        central,
        peripheral
    }
    private NetworkType type_;
    protected hostType masterHost;
    public hostType getMasterHost(){
        return masterHost;             <--WISH, should return MyServer / Myclient in derived class
    }
    public virtual std::string getName();
}

class CentralNetwork<MyServer> : public GenericNetwork{
    public std::string getName(){
        return masterHost.serverName;             <--WISH, tiped and suggested by editor / compiler
    }
}

class PeripheralNetwork<MyClient>: public GenericNetwork{
    public std::string getName(){
        return masterHost.clientName;             <--WISH, tiped and suggested by editor / compiler
    }
}

我现在没有 C 项目,所以我在运行中重写了它,抱歉有任何错误......

4

3 回答 3

0

没有明确约束模板参数 (*) 的专用功能,但您可以使用 (C++11's)

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
}
于 2014-02-02T01:00:39.000 回答
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);可以完成这项工作,但是绕过保护需要工作,而不仅仅是一个错误,它会出现在类型系统中,所以我看不出重点。

(编辑:添加虚拟析构函数,今晚我没有甜点。坏狗。)

于 2014-02-02T02:22:59.537 回答
0

据我所知,没有明确的功能可以让你做到这一点。不过你可以使用static_cast,如果类型不兼容,它会给你一个编译时错误。

template <class hostType>
class GenericNetwork {
public:
    GenericNetwork() {
        static_cast<GenericHost*>((hostType*)nullptr); // or 0 or NULL if not C++11
    }
};

如果hostTypeGenericHost是兼容的,演员将成功但什么也不做。否则,您将收到编译时错误。

于 2014-02-02T00:53:52.660 回答