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*
的容器中。