提问人:Kapibarovich Kapibarov 提问时间:10/17/2023 最后编辑:Remy LebeauKapibarovich Kapibarov 更新时间:10/20/2023 访问量:197
在没有特定返回类型的情况下编写纯虚函数的正确方法是什么?
What is the correct way to write pure virtual function without a specific return type?
问:
我正在尝试编写一个名为 的抽象结构,我需要派生类中的函数来计算从射线原点到我的形状的距离。我使用这里的函数,它们返回 、 、 等。我这样做是因为我需要将这些形状存储在稍后的向量中。这是个好方法吗?Shape
float
vec2
vec3
BasePrimitive
struct Shape {
virtual void* Intersect(const vec3& ro, const vec3& rd) = 0; // ro - rayOrigin, rd - rayDirection
};
struct Sphere : public Shape {
vec3 ce; // center
float ra; // radius
vec2 Intersect(const vec3& ro, const vec3& rd) override {
// some code
}
};
我试图通过 来做到这一点,但是当我插入时出现错误:void*
void*
返回类型与被覆盖的虚函数“Shape::Intersect”的返回类型“void *”不相同或协变
答:
2赞
Amit
10/17/2023
#1
如果你想要一个可以返回 ANY TYPE 的函数,一个选项是执行如下操作:
#include <any> // For 'std::any' and 'std::any_cast' (Since C++17)
#include <string>
class BC // Abstract polymorphic base class
{
public:
virtual std::any f() = 0; // Pure virtual
virtual ~BC() = default; // Virtual destructor (For an abstract polymorphic base class, it is highly recommended to provide a virtual destructor)
};
class DC1 final : public BC
{
public:
std::any f() override
{
return 1.5; // double
}
};
class DC2 final : public BC
{
public:
std::any f() override
{
return std::string("Pluto"); // std::string
}
};
class DC3 final : public BC
{
public:
std::any f() override
{
return 0; // int
}
};
int main()
{
DC1 obj1{};
const auto a = std::any_cast<double>(obj1.f());
DC2 obj2{};
const auto b = std::any_cast<std::string>(obj2.f());
DC3 obj3{};
const auto c = std::any_cast<int>(obj3.f());
}
- 这种解决方案通常是一个糟糕的选择,通常源于糟糕的设计选择。尽管如此,它仍然是一个可行的选择,特别是在它不是由糟糕的设计选择引起的情况下。
--
对于一组 TYPES 这是更好的选择:
#include <variant> // For 'std::variant' and 'std::get' (Since C++17)
#include <string>
class BC // Abstract polymorphic base class
{
public:
using SetOfTypes = std::variant<double, std::string, int>;
virtual SetOfTypes f() = 0; // Pure virtual
virtual ~BC() = default; // Virtual destructor (For an abstract polymorphic base class, it is highly recommended to provide a virtual destructor)
};
class DC1 final : public BC
{
public:
SetOfTypes f() override
{
return 1.5; // double
}
};
class DC2 final : public BC
{
public:
SetOfTypes f() override
{
return std::string("Pluto"); // std::string
}
};
class DC3 final : public BC
{
public:
SetOfTypes f() override
{
return 0; // int
}
};
int main()
{
DC1 obj1{};
const auto a = std::get<double>(obj1.f());
DC2 obj2{};
const auto b = std::get<std::string>(obj2.f());
DC3 obj3{};
const auto c = std::get<int>(obj3.f());
}
评论
2赞
user4581301
10/17/2023
请注意,这几乎总是一个由设计错误导致的坏主意。如果你必须这样做,请停下来想一想是什么把你带到了这里。
1赞
Remy Lebeau
10/17/2023
std::variant
在这个例子中,肯定是比std::any
0赞
Amit
10/17/2023
@RemyLebeau,首先,我同意。但是,OP 要求任何类型。std::variant 用于预定义的类型集。无论如何,我还添加了解决方案。std::variant
0赞
Thomas Matthews
10/17/2023
恕我直言,更好的方法是通过参数返回值。这允许将函数重载作为替代方法。
评论
void*
float
std::vector<float>