C++ 需要关于多重继承和可选函数重写C++;

C++ 需要关于多重继承和可选函数重写C++;,c++,templates,inheritance,polymorphism,overriding,C++,Templates,Inheritance,Polymorphism,Overriding,我试图解决一个问题,我希望有一些抽象基类,继承自多个类,其中派生可以选择性地重写它们的方法,而不声明额外的类。我将在这里举一个我试图实现的例子: #include <iostream> using namespace std; class A { public: virtual void foo() = 0; protected: A() {} }; class A1 : public A { public:

我试图解决一个问题,我希望有一些抽象基类,继承自多个类,其中派生可以选择性地重写它们的方法,而不声明额外的类。我将在这里举一个我试图实现的例子:

#include <iostream>

using namespace std;

class A
{
    public:
        virtual void foo() = 0;

    protected:
        A() {}
};

class A1 : public A
{
    public:
        A1() : A() {}

        void foo() { cout << "A1 foo" << endl; };
};

class A2 : public A
{
    public:
        A2() : A() {}

        void foo() { cout << "A2 foo" << endl; };
};

class B
{
    public:
        virtual void bar() { cout << "B bar: " << endl; }
};

class B1 : public B
{
    public:
        void bar()
        {
            cout << "B1 bar wrapper begin" << endl;
            B::bar();
            cout << "B1 bar wrapper end" << endl;
        }
};

/*
  ???
  pure virtual class C
  enforce derived classes to inherit something of type A
  enforce derived classes to inherit something of type B

  class C1 : public A1, either B or B1 ??? templates???
  {

  }

  class C2 : public A2, either B or B1 ??? templates???
  {

  }

  Can this be done without having to define classes CA1B, CA2B, CA1B1, CA2B1, etc.?
*/

int main(int argc, char *argv[])
{
    A1 a1;
    a1.foo();
    A2 a2;
    a2.foo();

/*
    C1 c1b with type B
    C1 c1b1 with type B1
    C2 c2b with type B
    C2 c2b1 with type B1

    put c1b, c1b1, c2b, c2b1 in a list named "combinations"

    cout << "Printing combinations" << endl;
    for (auto i : combinations)
    {
        i->foo();
        i->bar();
    }
*/

    return 0;
}
如果有办法通过某种设计模式来实现这一点,或者我使用了一种不好的方法,请让我知道。我使用的是C++11。

您的用例高呼“带约束的模板”。您缺少的是如何检查和编码模板参数是否从正确的类继承。您可以使用
std::is_base_of

template<class A_, class B_,
         typename std::enable_if<std::is_base_of<A, A_>::value>, int>::type = 0,
         typename std::enable_if<std::is_base_of<B, B_>::value>, int>::type = 0>
class C : public A_, public B_
{

};
template您的用例高呼“带约束的模板”。您缺少的是如何检查和编码模板参数是否从正确的类继承。您可以使用
std::is_base_of

template<class A_, class B_,
         typename std::enable_if<std::is_base_of<A, A_>::value>, int>::type = 0,
         typename std::enable_if<std::is_base_of<B, B_>::value>, int>::type = 0>
class C : public A_, public B_
{

};

template不久前我对这个主题很感兴趣,所以我有一些策略。我认为套接字程序是这种抽象的完美演示。最简单的方法之一是声明一个基头,其中包含您希望在所声明类的任何对象中可用的函数和变量。然后,当基类本身被设置为模板参数时,创建从基类继承的类。例如:

template<class P> class Socket {
  protected:
   int sock;
   char datagram[4096];
   struct sockaddr_in server;
   struct sockaddr_in b;
  public:
   void dport(int port){server.sin_port=htons(port);}
   int CONNECT(){return connect(sock , (struct sockaddr *)&server , sizeof(server));};
  template <class Dst> inline void dst(Dst d){server.sin_addr.s_addr=inet_addr(d);}
  template <class Src> void src(Src s){b.sin_addr.s_addr=inet_addr(s);}  
  int LISTEN(int port){b.sin_port=htons(port); return bind(sock,
  (sockaddr*)&b, sizeof(b));}
模板类套接字{
受保护的:
int袜子;
字符数据报[4096];
服务器中的结构sockaddr_;
b中的结构sockaddr_;
公众:
void dport(int-port){server.sin_-port=htons(port);}
int CONNECT(){return CONNECT(sock,(struct sockaddr*)&server,sizeof(server));};
模板内联void dst(dst d){server.sin_addr.s_addr=inet_addr(d);}
模板void src(src s){b.sin_addr.s_addr=inet_addr(s)}
int-LISTEN(int-port){b.sinu-port=htons(port);返回绑定(sock,
(sockaddr*)&b,sizeof(b));}
在这一点上,有几种方法可以专门化。我最喜欢的方法是创建新的类,这些类通过将自己的名称作为模板参数传递给base来继承

class UDP : public Socket<UDP> {
public:
    UDP(){server.sin_family=AF_INET;
    this->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);}
    template <class Msg> int SEND(Msg m, int length){
    return sendto(this->sock, m, length, MSG_DONTWAIT, (sockaddr*)&this-
    >server, sizeof(this->server));}
    void RECV(void* buf, size_t size){socklen_t fromlen = sizeof(sockaddr);
    ssize_t i = recvfrom(this->sock, buf, size, MSG_WAITALL,
    (sockaddr*)&this->b, &fromlen);}
};

class TCP : public Socket<TCP> {
public:
 TCP(){this->sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); this-
 >server.sin_family=AF_INET;}
 int SEND(std::string buf){return send(this->sock, buf.c_str(), buf.size(), 0);}   //TODO: Error Handling
 void RECV(){char cur; while (read(this->sock, &cur, 1) > 0 ) {cout << cur;}}};
class-UDP:公共套接字{
公众:
UDP(){server.sin_family=AF_INET;
this->sock=socket(AF_INET,sock_DGRAM,IPPROTO_UDP);}
模板int发送(消息m,int长度){
返回sendto(this->sock,m,length,MSG_DONTWAIT,(sockaddr*)和this-
>服务器,sizeof(此->服务器));}
void RECV(void*buf,size\u t size){socklen\u t fromlen=sizeof(sockaddr);
ssize_t i=recvfrom(此->袜子、小布袋、尺码、味精等),
(sockaddr*)&this->b,&fromlen);}
};
类TCP:公共套接字{
公众:
TCP(){this->sock=socket(AF_INET,sock_STREAM,IPPROTO_TCP);这个-
>server.sinu family=AF\u INET;}
int SEND(std::string buf){return SEND(this->sock,buf.c_str(),buf.size(),0);}//TODO:错误处理

void RECV(){char cur;while(读取(this->sock,&cur,1)>0){cout我之前对这个主题很感兴趣,所以我有一些策略。我认为套接字程序是这种抽象类型的完美演示。最简单的方法之一是声明一个基头,其中包含您希望在您声明的类的任何对象中可用的函数和变量。然后创建从当基类本身被设置为模板参数时,该基类即为基类。例如:

template<class P> class Socket {
  protected:
   int sock;
   char datagram[4096];
   struct sockaddr_in server;
   struct sockaddr_in b;
  public:
   void dport(int port){server.sin_port=htons(port);}
   int CONNECT(){return connect(sock , (struct sockaddr *)&server , sizeof(server));};
  template <class Dst> inline void dst(Dst d){server.sin_addr.s_addr=inet_addr(d);}
  template <class Src> void src(Src s){b.sin_addr.s_addr=inet_addr(s);}  
  int LISTEN(int port){b.sin_port=htons(port); return bind(sock,
  (sockaddr*)&b, sizeof(b));}
模板类套接字{
受保护的:
int袜子;
字符数据报[4096];
服务器中的结构sockaddr_;
b中的结构sockaddr_;
公众:
void dport(int-port){server.sin_-port=htons(port);}
int CONNECT(){return CONNECT(sock,(struct sockaddr*)&server,sizeof(server));};
模板内联void dst(dst d){server.sin_addr.s_addr=inet_addr(d);}
模板void src(src s){b.sin_addr.s_addr=inet_addr(s)}
int-LISTEN(int-port){b.sinu-port=htons(port);返回绑定(sock,
(sockaddr*)&b,sizeof(b));}
在这一点上,有几种方法可以专门化。我最喜欢的方法是创建新的类,这些类通过将自己的名称作为模板参数传递给base来继承

class UDP : public Socket<UDP> {
public:
    UDP(){server.sin_family=AF_INET;
    this->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);}
    template <class Msg> int SEND(Msg m, int length){
    return sendto(this->sock, m, length, MSG_DONTWAIT, (sockaddr*)&this-
    >server, sizeof(this->server));}
    void RECV(void* buf, size_t size){socklen_t fromlen = sizeof(sockaddr);
    ssize_t i = recvfrom(this->sock, buf, size, MSG_WAITALL,
    (sockaddr*)&this->b, &fromlen);}
};

class TCP : public Socket<TCP> {
public:
 TCP(){this->sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); this-
 >server.sin_family=AF_INET;}
 int SEND(std::string buf){return send(this->sock, buf.c_str(), buf.size(), 0);}   //TODO: Error Handling
 void RECV(){char cur; while (read(this->sock, &cur, 1) > 0 ) {cout << cur;}}};
class-UDP:公共套接字{
公众:
UDP(){server.sin_family=AF_INET;
this->sock=socket(AF_INET,sock_DGRAM,IPPROTO_UDP);}
模板int发送(消息m,int长度){
返回sendto(this->sock,m,length,MSG_DONTWAIT,(sockaddr*)和this-
>服务器,sizeof(此->服务器));}
void RECV(void*buf,size\u t size){socklen\u t fromlen=sizeof(sockaddr);
ssize_t i=recvfrom(此->袜子、小布袋、尺码、味精等),
(sockaddr*)&this->b,&fromlen);}
};
类TCP:公共套接字{
公众:
TCP(){this->sock=socket(AF_INET,sock_STREAM,IPPROTO_TCP);这个-
>server.sinu family=AF\u INET;}
int SEND(std::string buf){return SEND(this->sock,buf.c_str(),buf.size(),0);}//TODO:错误处理

void RECV(){char cur;while(读取(this->sock,&cur,1)>0){这样的东西能以多态的方式使用吗?例如,如果我创建一个
共享的ptr
对象和另一个
共享的ptr
对象,这两个对象都能存储在a
列表中吗?我不确定在C类中需要什么来将某个派生版本转换为
C
@George-No。或者使用模板te或明确说明(如在您的问题中)
C
C
不是多态关系。@George-但是你可以把所有这些类放在
B*
a*
的容器中。这样的东西能以多态方式使用吗?例如,如果我创建一个
shared\u ptr
对象和另一个
shared\u ptr
对象,这两个都可以存储在a
列表中吗
?我不确定C类中需要什么来将某个派生版本转换为
C
@George-No。可以使用模板,也可以显式拼写(如您的问题中所述)
C
C
不是多态关系。@George-但您可以将所有这些类放入
B*
a*
的容器中。