You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++编译报错:Mario类无默认构造函数问题求助

问题:Mario类无默认构造函数导致编译错误

我尝试创建一个存储程序全局通用信息的struct,计划在Mario::init()函数中更新该信息,但编译时出现如下错误:

No default constructor exists for class "Mario"

主文件代码

#include <SFML/Graphics.hpp>
#include <iostream>
    
#include "Mario.hpp"
    
int main()
{
    sf::RenderWindow window(sf::VideoMode(1920, 1080), "SFML works!");
    window.setFramerateLimit(60);
    
    Mario m;
    
    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed) window.close();
        }
    
        window.clear();
        //m.update(window);
        window.display();
    }
    
    return 0;
}

头文件(Mario.hpp)代码

#include <SFML/Graphics.hpp>
    
#ifndef MARIO_HPP
#define MARIO_HPP

struct M_info {
    sf::Texture textureMario;
    sf::Sprite mario;
    int x = 100;
    int y = 100;
    bool Initialized = false;
};
    
struct Mario {
    M_info& m_info;
    
    Mario(M_info& m_info_s) : m_info(m_info_s){}
    
    void init();
    void update(sf::RenderWindow&);
};
    
#endif

源文件(Mario.cpp)代码

#include "Mario.hpp"
#include <SFML/Graphics.hpp>
#include <iostream>

void Mario::init()
{
    if(!m_info.textureMario.loadFromFile("C:\\Users\\beheerder\\source\\repos\\Mario\\images\\mario.png")) std::cout << "FAILED TO LOAD MARIO.";
    m_info.mario.setTexture(m_info.textureMario);
    std::cout << "Loaded texture\n";
}

void Mario::update(sf::RenderWindow& window)
{
    window.draw(m_info.mario);
}

注释掉头文件中的以下两行时,程序可正常编译:

M_info& m_info;
Mario(M_info& m_info_s) : m_info(m_info_s){}

但取消注释后,主文件会报两个错误:

No default constructor exists for class "Mario"
Local variable not initialized

我试过给成员添加默认值、创建默认构造函数,但均未成功,希望得到解决方法。


解决方案

问题根源有两点:

  1. 自定义Mario的构造函数后,C++不会自动生成默认构造函数(无参数的构造函数),而main中Mario m;的写法正是在调用默认构造函数,因此报错。
  2. Mario中的m_info是引用类型,引用必须在对象初始化时就绑定到一个已存在的有效对象,无法默认初始化。

思路1:先创建M_info对象,再传入Mario构造函数(推荐)

修改main函数,先实例化M_info全局信息对象,再用它初始化Mario,完全符合引用的初始化要求:

int main()
{
    sf::RenderWindow window(sf::VideoMode(1920, 1080), "SFML works!");
    window.setFramerateLimit(60);
    
    M_info global_info; // 先创建全局信息实例
    Mario m(global_info); // 用已存在的M_info对象初始化Mario
    m.init(); // 调用init加载资源
    
    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed) window.close();
        }
    
        window.clear();
        m.update(window); // 取消注释启用渲染
        window.display();
    }
    
    return 0;
}

思路2:给Mario添加默认构造函数(不推荐)

如果一定要使用Mario m;的写法,需要让引用绑定到一个全局或静态的M_info对象,但这种方式可能破坏封装性,且需注意内存生命周期:
修改头文件中的Mario结构:

struct Mario {
    M_info& m_info;

    // 辅助函数提供静态全局M_info实例
    static M_info& get_global_info() {
        static M_info info;
        return info;
    }
    
    // 默认构造函数,绑定到静态全局实例
    Mario() : m_info(get_global_info()) {} 
    Mario(M_info& m_info_s) : m_info(m_info_s){}
    
    void init();
    void update(sf::RenderWindow&);
};

这种方式依赖静态对象,仅适合确实需要单一全局实例的场景。

额外提示

  • 引用类型的成员变量必须在构造函数的初始化列表中完成绑定,无法在构造函数体内赋值,这也是你之前尝试添加默认值失败的原因。
  • 如果M_info确实是全局通用的,也可以考虑设计成单例模式,但需注意全局变量的初始化顺序问题。

内容的提问来源于stack exchange,提问作者ggjorven

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 22:32:48