我对c ++很陌生,所以我想知道如何在c ++中以正确的方式做事。我正在上一个使用两个成员之一的课程。哪一个在实例化时得到确定。它看起来像
main() {
shared_pointer<A> a = make_shared<A>();
if ( checkSomething ) {
a->setB(make_shared<B>());
} else {
a->setC(make_shared<C>());
}
a->doStuff();
class A {
public:
doStuff() {
/*here I want to do something like call
m_b->doStuff() if this pointer is set and m_c->doStuff() if
that pointer is set.*/
}
setB( B* p ) { m_b = p; }
setC( C* p ) { m_c = p; }
B* m_b;
C* m_c;
}
}
B and C are some classes with doStuff() member function
像doStuff这样的成员很多。理想情况下,我会避免在每个中检查nullptr。在这两个成员之间创建切换的最佳/最有效/最快的方法是什么?
有没有办法使用静态指针,以便我有一个成员
static **int m_switch;
并执行类似
的操作m_switch = condition ? &m_b : &m_c;
并致电
*m_switch->doStuff();
这里的编译器是否也替换额外的指针跳,因为它是静态的?
还有其他智能方法可以做这些开关吗?
答案 0 :(得分:4)
通常,类A
将是接口类,B
和C
都将继承和实现。但听起来你出于某种原因无法做到这一点。
由于你想模仿这个,你可以先创建界面:
class A_interface
{
public:
virtual void doStuff() = 0;
virtual void doThings() = 0;
virtual void doBeDoBeDo() = 0;
};
然后你制作一个模板包装器:
template< class T >
class A : public A_interface
{
public:
void doStuff() override { target.doStuff(); }
void doThings() override { target.doThings(); }
void doBeDoBeDo() override { target.doBeDoBeDo(); }
private:
T target;
};
这基本上是您自己的示例类A
尝试执行的操作的一半,但现在您可以使用通用接口。您需要做的就是构建所需的正确模板版本:
std::shared_ptr<A_interface> a;
if( checkSomething ) {
a = std::make_shared<A<B>>();
} else {
a = std::make_shared<A<C>>();
}
a->doStuff();
答案 1 :(得分:1)
对于您的问题,没有一个通用的解决方案。使用方法取决于您的具体问题。一些可能的答案:
界面就像合约。从接口继承的任何类都必须实现其成员。例如,
class IDoesStuff
{
public:
virtual ~IDoesStuff() {};
virtual void DoStuff() = 0;
};
现在可以被其他类使用:
class Foo : public IDoesStuff
{
public:
virtual void DoStuff()
{
// ....
}
};
class Bar : public IDoesStuff
{
public:
virtual void DoStuff()
{
// ....
}
};
现在,一般情况下,人们可以这样做:
Foo foo;
IDoesStuff *stuffDoer= &foo;
stuffDoer->doStuff();
这可以在您的特定用例中使用,如下所示:
class A
{
IDoesStuff *stuffDoer; // Initialize this at some point.
public:
void doStuff() { stuffDoer->doStuff(); }
};
答案 2 :(得分:1)
您需要让两个成员都实现一个通用接口,以便类似地使用它们。但为了做到这一点,您需要定义接口并将调用中继到B和C类。
// existing classes
class B
{
public:
void doStuff() { std::cout << "B"; }
};
class C
{
public:
void doStuff() { std::cout << "C"; }
};
// define your interface
class I
{
public:
virtual void doStuff() = 0;
};
// new classes
class D : public B, public I
{
public:
void doStuff() override { B::doStuff(); }
};
class E : public C, public I
{
public:
void doStuff() override { C::doStuff(); }
};
// your A class
class A
{
public:
D* b = nullptr; // now type D
E* c = nullptr; // now type E
// your toggle
I* getActive()
{
if (b)
return b;
else
return c;
}
// simple doStuff() function
void doStuff()
{
getActive()->doStuff();
}
};
int main()
{
A a;
if (true)
a.b = new D; // need to initialize as D
else
a.c = new E; // need to initialize as E
a.doStuff(); // prints B
}
但输入此内容后,我意识到定义D
和E
可能会让您感到非常厌烦,并且反对您尝试保存的内容。但是,您可以定义一个模板来创建它们,就像@paddy所做的那样。
答案 3 :(得分:1)
首先,您必须将您的memebr变量m_b
和m_c
更改为std::shared_ptr
。
添加类型std::function(void())
的成员变量以保存要调用的目标函数。在您的示例中,它是do_stuf
。
在你的setter函数中,你可以将目标函数绑定到std::function
和do_stuf
,只需调用std::function
。
(您需要一个C ++ 11编译器)
class B
{
public:
void doStuff()
{
}
};
class C
{
public:
void doStuff()
{
}
};
class A
{
public:
void doStuff()
{
m_target_function();
}
void setB(std::shared_ptr<B> p)
{
m_b = p;
m_target_function = std::bind(&B::doStuff, m_b.get());
}
void setC(std::shared_ptr<C> p)
{
m_c = p;
m_target_function = std::bind(&C::doStuff, m_c.get());
}
std::shared_ptr<B> m_b;
std::shared_ptr<C> m_c;
std::function<void()> m_target_function;
};
int _tmain(int argc, _TCHAR* argv[])
{
std::shared_ptr<A> a = std::make_shared<A>();
bool use_B = false;
if (use_B)
{
a->setB(std::make_shared<B>());
}
else
{
a->setC(std::make_shared<C>());
}
a->doStuff();
}