gpt4 book ai didi

c++ - 在C++中的堆栈上创建实例时如何保持多态性?

转载 作者:行者123 更新时间:2023-12-01 14:42:41 26 4
gpt4 key购买 nike

在堆上创建实例并保持多态性,这将给出正确的答案:

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();
}
}

打印:

Father say hello
Son say hello
Father say hello


您还可以阅读以下内容:
  • Sean Parent's better-code-runtime-polymorphism
  • discussion about its usage
  • 关于c++ - 在C++中的堆栈上创建实例时如何保持多态性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62340673/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com