无法实例化包含用户定义类型的类
Posted
技术标签:
【中文标题】无法实例化包含用户定义类型的类【英文标题】:Cannot instantiate class containing user-defined type 【发布时间】:2015-12-17 21:18:02 【问题描述】:我对 Java 有深入的了解,但我正在尝试学习 c++ 来制作游戏,因为我认为 c++ 是一种更好的语言。但是我在使用 c++ 时遇到了一些问题。
#ifndef RENDER_H
#define RENDER_H
#include "shader.h"
class Render
public:
Render();
protected:
private:
Shader shader;
;
#endif
Shader
是一个带有字符串构造函数的类,只是在这个类中声明它会导致错误。如果我删除 Shader
的构造函数,我不会收到错误消息。
Error: render.cpp:3:16: error: no matching function for call to 'Shader::Shader()'
class Shader
public:
Shader(const std::string& fileName);
void Bind();
void Update(const Transform& transform, const Camera& camera);
virtual ~Shader();
【问题讨论】:
您应该显示Shader
的代码(至少它是构造逻辑和Render
构造函数的实现。听起来您可能没有默认构造函数,因此您需要1)添加默认构造函数或2)正确使用Render
构造函数中的initiailzer列表来实例化Shader
对象。
请发帖minimal reproducible example。说出您遇到的错误也很有用。
@AlanStokes 它指出错误是对 Shader
类的缺失默认构造函数的调用。
错误出现在您未向我们展示的函数中。见minimal reproducible example。
不要以使已发布答案无效的方式更改问题。
【参考方案1】:
shader
是Render
的类成员。在实例化Render
对象时,需要沿途构造Shader
对象。由于它不提供默认的 c'tor,因此无法构造它(这就是错误消息告诉您的内容)。
要解决此问题,请为 Shader
1) 提供默认 c'tor,或为 Render
s c'tor 使用初始化列表:
Render::Render() : shader("foo")
或
Render::Render(const std::string& shaderFilename) : shader(shaderFilename)
1)注意:如果没有定义任何 c'tor,编译器会生成一个默认 c'tor。这就是为什么删除
Shader
s 自定义 c'tor 似乎可以解决问题的原因。
【讨论】:
【参考方案2】:您的问题在于 Render
构造函数(未在您的问题中显示)。因为您的类Render
有一个成员变量Shader
,它只有一个构造函数(采用std::string
参数),所以您必须在构造函数初始化列表中显式调用该构造函数:
Render::Render()
: shader("MyRenderShader"); // construct the Shader
如果我删除 Shader 的构造函数,我不会收到错误消息。
请注意,当您删除 Shader
构造函数时,编译器会删除 generates a default constructor for you,这意味着您不需要显式调用 Render
中的构造函数(尽管您应该这样做)。
【讨论】:
【参考方案3】:这是你的描述
Shader 是一个带有字符串构造函数的类,只是在 this 中声明它 类导致错误。如果我删除着色器的构造函数,我不会 得到错误
描述问题。如果您没有在构造函数 Render 的 mem-initializer 列表中显式调用类 Shader 的构造函数,则编译器会尝试调用数据成员 Shader shader;
的默认构造函数。但是它没有被声明,编译器会报错。
要么调用构造函数Render的mem-initializer列表中的Shader类的构造函数指定参数,要么定义Shader类的默认构造函数。
【讨论】:
【参考方案4】:您很可能没有在 Render 构造函数中将字符串提供给 Shader 构造函数。你的渲染构造函数需要做这样的事情:
Render::Render()
: shader("This is the string parameter of the shader")
但正如我所见,您的 Shader 是虚拟类,您很可能实际上希望着色器具有多态性。在这种情况下,您实际上需要将 is 存储为指针,并可能将实际实现提供给 Render 构造函数,例如:
class Render
public:
Render(Shader *p_shader = NULL)
: shader(p_shader)
~Render()
delete shader;
protected:
private:
Shader *shader;
;
并且要么禁用复制构造和分配,要么同时提供它们,并确保在那里复制着色器以避免破坏时双重释放。
最好还是使用 std::unique_ptr 甚至 std::shared_ptr(使用 shared_ptr 你可以使用编译器生成的副本和赋值)。
在声明 Java 背景时,请记住 Java 引用的等价物是 C++ 中的指针,即 Java 代码:
Shader shader = new Shader();
在 C++ 中翻译为:
Shader *shader = new Shader();
(并且没有可用的垃圾收集,这就是使用智能指针的原因)。
【讨论】:
以上是关于无法实例化包含用户定义类型的类的主要内容,如果未能解决你的问题,请参考以下文章