如何理解C ++变量范围规则?

时间:2016-01-11 23:42:01

标签: c++ class scope segmentation-fault extern

我最近从PHP和LSL等脚本语言返回到C ++,其中一些范围规则让我感到困惑。

说我有一个像这样的Viewer.h:

class Viewer {

    public:

        Viewer();
        ~Viewer();

        void    ping();
        void    setBgColour(int r, int g, int b, int a);

        float   bg_r;
        float   bg_g;
        float   bg_b;
        float   bg_a;
};

和Viewer.C一样:

#include "Globals.h"
#include "Viewer.h"

Viewer::Viewer() {}
Viewer::~Viewer() {}

void Viewer::ping() {

    cout << "Viewer::ping() " << endl;
}

void Viewer::setBgColour(int r, int g, int b, int a) {

    bg_r = r/255.0;
    bg_g = g/255.0;
    bg_b = b/255.0;
    bg_a = a/255.0;
}

我已在Global中声明了我的查看器类的实例。{h | C}为&#39; extern&#39;为了能够从其他文件访问全局查看器实例。

现在考虑一下,当我在例如UI.C中调用全局查看器实例方法时:

viewer->ping();
viewer->setBgColour(123, 45, 56, 255);

viewer-&gt; ping()工作正常,但是viewer-&gt; setBgColour()在尝试访问实例变量bg_r,bg_g,bg_b和bg_a时给了我一个分段错误。

我的理解是我没有访问正确的查看器实例。

viewer-&gt; ping()并不关心,因为无论实际调用它的实例如何,它都会将文本回显给cout。但是setBgColour()需要访问正确的内存位置,因此当它无法找到它们时会出现段错误。

这让我感到困惑,因为我/我的印象是宣称我的观众实例为“外部”。会“只是工作”。傻我。我已经尝试将变量声明为&#39;静态&#39;但这让我更加困惑。

2 个答案:

答案 0 :(得分:1)

如果在发布行之前代码中的viewer没有完成,那么你有未初始化的指针Viewer* viewer。取消引用此类指针会导致分段错误。如果要修复它,则应将创建的对象的地址分配给指针。

可能:

(在main开头)

viewer = new Viewer();

// some code here

delete viewer;

或者为其分配现有全局变量的地址。

答案 1 :(得分:0)

不要使用全局实例,而应考虑使用单例。实际上没有必要在堆上分配您的查看器。

e.g。

#include <iostream>
using std::cout;

class Viewer 
{
    float   bg_r;
    float   bg_g;
    float   bg_b;
    float   bg_a;

    Viewer(Viewer const&) = delete;
    Viewer& operator=(Viewer const&) = delete;

    public:

    Viewer()
        : bg_r(0.0), bg_g(0.0), bg_b(0.0), bg_a(0.0)
    {}
    void    ping();
    void    setBgColour(int r, int g, int b, int a);      
};

void Viewer::ping() 
{
    cout << "Viewer::ping()\n";
}

void Viewer::setBgColour(int r, int g, int b, int a) 
{
    bg_r = r/255.0;
    bg_g = g/255.0;
    bg_b = b/255.0;
    bg_a = a/255.0;
}

Viewer& GetViewer()
{
    static Viewer v;
    return v;
}

int main()
{
    GetViewer().ping();
    GetViewer().setBgColour(1,2,3,4);
}