在堆上创建实例并保持多态性,这将给出正确的答案:
class Father
{
public:
virtual void Say()
{
cout << "Father say hello" << endl;
}
};
class Son : public Father
{
public:
void Say()
{
cout << "Son say hello" << endl;
}
};
int main()
{
std::vector<Father*> v;
std::cout << 1 << std::endl;
for(int i(0); i<5; i++)
{
auto p = new Son(); ---------------on heap
v.emplace_back(p);
}
for(auto p : v)
{
p->Say();
}
}
但是,当我想在堆栈上创建一个实例时,似乎并不容易:
版本1:
class Father
{
public:
virtual void Say()
{
cout << "Father say hello" << endl;
}
};
class Son : public Father
{
public:
void Say()
{
cout << "Son say hello" << endl;
}
};
int main()
{
std::vector<Father> v;
for(int i(0); i<5; i++)
{
auto o = Son(); ---------------on stack
v.emplace_back(o);---------------now "o" is cast to Father type
}
for(auto o : v)
{
o.Say();------------------------only output "Father say hello"
}
}
和版本2:
class Father
{
public:
virtual void Say()
{
cout << "Father say hello" << endl;
}
};
class Son : public Father
{
public:
void Say()
{
cout << "Son say hello" << endl;
}
};
int main()
{
std::vector<Father*> v;
for(int i(0); i<5; i++)
{
auto p = &Son(); --------------On the stack
v.emplace_back(p);---------------Now "o" is cast to Father type
}
for(auto p : v)
{
p->Say();------------------------Since "p" now is a Wild pointer, it'll fail too
}
}
这个可以解决吗?还是仅仅是一个死胡同:如果我想使用多态性,那么我必须在堆上创建一个对象。
最佳答案
这是一个反复出现的问题/难题:您可以牺牲一些样板代码来维护值语义。这是这种想法的最小工作示例:
#include <iostream>
#include <memory>
#include <vector>
class Father
{
protected:
struct Father_Interface
{
virtual void
Say() const
{
std::cout << "Father say hello" << std::endl;
}
};
using pimpl_type = std::shared_ptr<const Father_Interface>;
pimpl_type _pimpl;
Father(const Father_Interface* p) : _pimpl(p) {}
public:
Father() : Father{new Father_Interface{}} {}
void Say() const { _pimpl->Say(); }
};
class Son : public Father
{
protected:
class Son_Interface : public Father_Interface
{
void
Say() const override
{
std::cout << "Son say hello" << std::endl;
}
};
public:
Son() : Father{new Son_Interface{}} {}
Son& operator=(const Father&) = delete; // fight against object slicing
};
int
main()
{
std::vector<Father> v;
v.emplace_back(Father());
v.emplace_back(Son());
v.emplace_back(Father());
for (const auto& v_i : v)
{
v_i.Say();
}
}
打印:
您还可以阅读以下内容: