假设我在两个不同文件的相同名称空间中有两个名称相同的类。
因此,我可以使用两个类中的每个类构造另一个对象,遵循相同的接口,但某些函数的行为有所不同。
对于行为不同的函数,我将在类的一个实例中重新定义它们。
对于功能相同的函数,我想构造另一个类的实例并转发调用。
有没有办法做到这一点?显然,我不能在同一个名称空间中拥有两个类,但是也许我可以重新定义我想成为成员的类的名称空间/类名,以便转发调用?
例如:
//file_1.h
namespace x {
class y {
}
}
//file_2.h
#include "file_1.h"
namespace x {
class y {
// member of same class in the other file
y memberName;
}
}
答案 0 :(得分:2)
在声明了一个类之后,您不能再对其进行修改,并且您不能声明两个具有相同名称的不同类。
您可以使用虚拟方法声明类层次结构,并使用指向基址的指针。例如:
class A {
public:
virtual void f() = 0;
};
class B : public A {
void f() override {std::cout << "B" << std::endl;}
};
class C : public A {
void f() override {std::cout << "C" << std::endl;}
};
int main()
{
A *a1 = new B;
A *a2 = new C;
a1->f(); // B
a2->f(); // C
return 0;
}
尽管a1
和a2
都是指向A
的指针,但代码将打印:
B
C
如果您不想公开此类层次结构,则可以使用pimpl technique。它允许您隐藏类的实际实现。 例如:
// File: A.h
class A {
class AImpl;
std::unique_ptr<AImpl> m_pimpl;
public:
explicit A();
void f();
};
// File A.cpp
class A::AImpl {
public:
void f() { std::cout << "A" << std::endl;};
};
A::A() : m_pimpl(new AImpl) {
}
void A::f() {
m_pimpl->f();
}
现在,您可以在cpp文件中定义类AImpl的实现。您甚至可以对AImpl
使用类层次结构,以根据内部创建的类来创建不同的行为对象。
答案 1 :(得分:2)
假设我在两个不同文件的相同名称空间中有两个名称相同的类。
然后您违反了称为ODR的规则或一个定义规则。这样做会使您的程序格式错误,不需要进行诊断。
如果您有一个类Alice
要使用另一个类Bob
,但又想为Bob
的工作方式使用两个不同的定义,则解决方案称为“多态”。
多态性是两个或多个类替代一个类的能力。
存在三种简单的多态形式。使用了虚拟接口和运行时多态。有使用模板和编译时拟态。然后通过函数指针进行类型擦除。
最简单的方法是定义虚拟接口。
struct IBob {
virtual int count() const = 0;
virtual ~IBob() {}
};
struct Alice {
std::unique_ptr<IBob> my_bob = nullptr;
void do_stuff() const {
if(my_bob) std::cout << "Count is:" << my_bob->count() <<"\n";
}
};
现在我们可以定义IBob
的两种实现:
struct Bob0:IBob{
int count() const final { return 7; }
};
struct Bob1:IBob{
std::unique_ptr<IBob> pBob;
int count() const final {
if(pBob) return pBob->count()*2 +1;
else return 1;
}
};
现在Bob1
有一个IBob
,它使用该IBob
来实现自己的count
。
模板方式如下:
template<class Bob>
struct Alice {
Bob my_bob;
void do_stuff() const {
std::cout << "Count is:" << my_bob.count() <<"\n";
}
};
和各种Bob
实现无需virtual
或继承。在这里,您必须在每次使用时在编译时选择哪个Bob
。
手动功能指针类型的擦除解决方案更加复杂。我不建议这样做。
答案 2 :(得分:0)
包含文件时,就像将内容添加到该cpp文件一样。 因此,这意味着您将为不同的类使用相同的名称。
可以使用typedef使用相同的名称。
class A {
public:
static void func() {}
};
class B {
public:
static void func() {}
};
void funcA() {
typedef A C;
C::func();
}
void funcB() {
typedef B C;
C::func();
}
int main()
{
funcA();
funcB();
return 0;
}