无法实例化包含用户定义类型的类

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】:

shaderRender 的类成员。在实例化Render 对象时,需要沿途构造Shader 对象。由于它不提供默认的 c'tor,因此无法构造它(这就是错误消息告诉您的内容)。

要解决此问题,请为 Shader1) 提供默认 c'tor,或为 Renders c'tor 使用初始化列表:

Render::Render() : shader("foo") 

Render::Render(const std::string& shaderFilename) : shader(shaderFilename) 


1)注意:如果没有定义任何 c'tor,编译器会生成一个默认 c'tor。这就是为什么删除 Shaders 自定义 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();

(并且没有可用的垃圾收集,这就是使用智能指针的原因)。

【讨论】:

以上是关于无法实例化包含用户定义类型的类的主要内容,如果未能解决你的问题,请参考以下文章

Jackson JSON 库:如何实例化包含抽象字段的类

显式实例化模板类的显式实例化模板方法

在 C# 中的另一个对象内实例化用户定义的对象

PHP能在类中实例化一个类吗

在Typescript中,如何在工厂(ish)函数中实例化的类上获取方法的通用返回类型

python的类定义与实例化