这可能是C ++编码标准中解释的关闭规则的情况,我想知道我是否正确地执行了此操作。我想知道因为我在切换功能中仍然有if子句。
类A
永远不会直接实例化,它始终是动态创建的B
或C
,并通过指向A
的(共享)指针统一处理。 foo
根据是B
还是C
来切换并选择操作。
class A {
public:
virtual ~A(){}
};
class B : public A {};
class C : public A {};
typedef std::shared_ptr<A> Aptr;
typedef std::shared_ptr<B> Bptr;
typedef std::shared_ptr<C> Cptr;
template<class T>
std::shared_ptr<T> get(const Aptr& pA) {
return std::dynamic_pointer_cast< T >( pA );
}
void foo( const Bptr& pB ) {
std::cout << "operate on B\n";
}
void foo( const Cptr& pC ) {
std::cout << "operate on C\n";
}
void foo( const Aptr& pA ) {
if ( auto x = get<B>(pA) ) {
foo(x);
return;
}
if ( auto x = get<C>(pA) ) {
foo(x);
return;
}
assert(!"oops");
}
int main()
{
Aptr pA( new C );
foo( pA );
}
我的问题是void foo( const Aptr& pA )
是否可以更优雅地实施。这可能意味着没有if
。投掷get
并在这种情况下推荐foo
?
答案 0 :(得分:2)
除非你有充分的理由否则(如果你有它们,你的代码没有显示它们),这在我看来就像通过虚函数实现的动态多态的典型用例:
class A
{
public:
virtual ~A() {}
virtual void foo() = 0;
};
class B : public A
{
virtual void foo()
{
std::cout << "operate on B\n";
}
};
class C : public A
{
virtual void foo()
{
std::cout << "operate on B\n";
}
};
此外,在C ++ 11中,最好使用std::make_shared<>()
来构建shared_ptr
并进行裸new
分配(同样,除非你有充分的理由否则):
int main()
{
Aptr pA = std::make_shared<C>();
pA->foo();
}
如果您有理由不使用虚函数并且喜欢不同的非侵入式多态,则可以将Boost.Variant与boost::static_visitor
结合使用。这甚至不需要B
和C
相关。
#include <boost/variant.hpp>
#include <memory>
#include <iostream>
class B /* ... */ {};
class C /* ... */ {};
// ...
typedef std::shared_ptr<B> Bptr;
typedef std::shared_ptr<C> Cptr;
struct foo_visitor : boost::static_visitor<void>
{
void operator () (Bptr p)
{
std::cout << "operate on B\n";
}
void operator () (Cptr p)
{
std::cout << "operate on C\n";
}
};
int main()
{
boost::variant<Bptr, Cptr> ptr;
ptr = std::make_shared<C>();
foo_visitor v;
ptr.apply_visitor(v);
}
这种方法与您选择的方法非常相似,除了Boost.Variant还确保您不会忘记为变体可能假设的每个值包含一个处理案例(在这种情况下,{{1} }和Bptr
)。
答案 1 :(得分:1)
只需使用虚拟成员函数。没有替代真实的东西
class A {
public:
virtual ~A(){}
virtual void foo() = 0;
};
class B : public A {
public:
virtual void foo() {
std::cout << "operate on B\n";
}
};
class C : public A {
public:
virtual void foo() {
std::cout << "operate on C\n";
}
};
并选择一个好的C++ introductory book。