我似乎无法找到答案,但也许我正在寻找错误的术语。我没有在点击中找到我正在寻找的答案。
我有一堆菜单系统的派生类。
我有一个CControl
派生类,它是CEditBox
和CLabel
类的父级。 CLabel
只不过是将文本附加到SDL_Surface上,然后将其绑定到用于渲染的openGL的纹理。 CEditBox
将是一个用于显示文本或从用户收集文本的字段,如密码框。显然,CEditBox可以使用标签来处理框内的文本呈现。 CControl
源自CComponent
。
我无法在CLabel
内声明CEditBox
,除非我在标题中包含CLabel
,但我认为即使我将所有标题都包含在{{{}}中,我仍然会收到链接器错误。 1}}语法,但我也是一个菜鸟。相反,我声明了#ifndef #define class #endif
指针,因为它们是从该类派生的。
精细。现在在我CComponent*
的构造函数中:
CEditBox
当这个构造函数返回时,CLabel不会超出范围,因此Feild会被销毁,现在我的指针指向一个未定义的内存块吗?什么是适当的方法来做到这一点?有更好的解决方案吗?
谢谢
我不知道问题已经存在,但有些人认为这是一个更重要的问题。那么现在是实际的代码,你们可以告诉我你是否认为它是错误的。 基类CMenuObject
#include "CLabel.h" //include in .CPP is fine I reckon.
CEditBox::CEditBox() {
CLabel Field; //Create CLabel
InputType = ALL; //Not important for my question related to allowed symbols
Label = &Field; //CComponent pointer to CLabel
}
下一课是CComponent
#ifndef _CMENUOBJECT_H_
#define _CMENUOBJECT_H_
class CMenuObject {
protected:
const char* ClassName;
public:
CMenuObject();
virtual const char* Object();
};
#endif
然后是CControl这些将是用户将与之交互或以某种方式需要控制显示的对象(即,计时器不需要用户输入)并且是一个巨大的。不介意函数指针的东西,因为我不知道我在做什么呢......这是我处理事件的第一个猜测方法。我认为这是有限的,因为如果函数需要参数但我可能不需要等等我无法弄清楚该做什么......我们现在可以掩盖这个细节。
#ifndef _CCOMPONENT_H_
#define _CCOMPONENT_H_
#include "CMenuObject.h"
class CComponent : public CMenuObject {
protected:
const char* _Name;
int _Tag;
static int _ComponentCount;
static int _IDCount;
public:
CComponent();
virtual const char* Name();
virtual int Tag();
virtual void Tag(int t);
};
#endif
最后我的CLabel和CEditBox的游戏标题。
#ifndef _CCONTROL_H_
#define _CCONTROL_H_
#include "CComponent.h"
class CControl : public CComponent {
protected:
int _X,_Y,_Width,_Height;
float R,G,B,A;
void (*OnClk)();
void (*OnDblClk)();
void (*OnMOver)();
void (*OnMHover)();
void (*OnKDown)();
void (*OnKUp)();
void (*OnFcs)();
bool Visible;
CComponent* Pappy;
public:
CControl();
//Render Control
virtual void Show(); // Show Component
virtual void Hide(); // Hide Component
virtual void OnRender(); // Render Component
virtual bool IsVisible(); // Get Current Visibility Status
//Paramater Control
//Write
virtual void X(int x); // Set Component's X coordinate
virtual void Y(int y); // Set Component's Y coordinate
virtual void Width(int w); // Set Component's Width
virtual void Height(int h); // Set Component's Height
//Read
virtual int X(); // Get Component's X coordinate
virtual int Y(); // Get Component's Y coordinate
virtual int Width(); // Get Component's Width
virtual int Height(); // Get Component's Height
//Display Control
virtual void Color(float r, float g, float b); // Set Color of Component- Multicolored objects, this will be the base or bkg color. Makes alpha 1.0f.
virtual void Color(float r, float g, float b, float a); // Same as above but allows for input of an alpha value.
//Font Control
virtual void FontName(const char* font); // Name of font to use
virtual void FontSize(int pt); // Pt size of font. Or maybe pixel, no idea.
virtual void Text(const char* msg); // Text message to render
//Read
virtual const char* Text(); // Read Text Message
//Interactive Control // These will register call back functions for user events
virtual void OnClick(void (*func)()); // On Single Click
virtual void OnDoubleClick(void (*func)()); // On Double Click
virtual void OnMouseOver(void (*func)()); // On Mouse Over
virtual void OnMouseHover(void (*func)()); // On Mouse Hover
virtual void OnKeyDown(void (*func)()); // On Key Down
virtual void OnKeyUp(void (*func)()); // On Key Up
virtual void OnFocus(void (*func)()); // On Focus
//Other
virtual void Parent(CComponent); // Set Parent
virtual CComponent* Parent(); // Get Parent
};
#endif
和
#ifndef _CLABEL_H_
#define _CLABEL_H_
#include "CTexture.h"
#include "CFont.h"
#include "CControl.h"
class CLabel : public CControl {
private:
const char* vText;
CFont Font;
CTexture Text_Font;
SDL_Surface* Surf_Text;
int X,Y,vWidth,vHeight;
public:
CLabel();
CLabel(const char* text);
virtual void OnRender();
virtual void OnCleanup();
virtual void Text(const char* msg);
virtual const char* Text();
virtual void FontName(const char* fname);
virtual void FontSize(int pt);
virtual void FontColor(float r, float g, float b);
};
#endif
今天,我发现一个dang标头没有包含在#ifndef #define #endif中。 (它是#ifndef _CEDITBOX_H_
#define _CEDITBOX_H_
#include "CControl.h"
class CEditBox : public CControl {
protected:
CComponent* Label;
int InputType;
public:
CEditBox();
~CEditBox();
virtual void OnRender();
//virtual void OnCleanup();
virtual void OnLoop();
virtual void Text(const char* msg);
virtual const char* Text();
virtual void FontColor(float r, float g, float b);
virtual void OnClick(void (*func)()); // On Single Click
virtual void OnDoubleClick(void (*func)()); // On Double Click
virtual void OnMouseOver(void (*func)()); // On Mouse Over
virtual void OnMouseHover(void (*func)()); // On Mouse Hover
virtual void OnKeyDown(void (*func)()); // On Key Down
virtual void OnKeyUp(void (*func)()); // On Key Up
virtual void OnFocus(void (*func)()); // On Focus
enum {
ALL = 0, //abcdefghijklmnopqrstuvwxyz (and caps) 1234567890!@#$%^&*()_+-=[]{}<>\/|"';:,.?
ALPHA_NUMERIC, //abcdefghijklmnopqrstuvwxyz (and caps) 1234567890
ALPHA, //abcdefghijklmnopqrstuvwxyz (and caps)
NUMERIC, //1234567890
PASSWORD, //abcdefghijklmnopqrstuvwxyz (and caps) 1234567890!@#$%&. -- Render as *
IP //1234567890 . Maybe fix feild width and force xxx.xxx.xxx.xxx format.
};
};
#endif
再次在CTexture
中调用。无论如何,重组也非常有用,因为我已经弄清楚如何使用继承和基类指针,以及派生类如何使用每个其他。更不用说还有很多东西。:)
我为派生类的相互作用所采用的路径是使用基类指针,该指针可以通过虚函数访问派生类函数。我使用new和delete,因为这是我很满意的。对于每个贡献的人,谢谢!他们都是很好的答案。
答案 0 :(得分:3)
立体声的典型方法是:
展示第二种方法:
//////////// CEditBox.hpp header file
#include <memory>
#include <string>
class CLabel; // forward declaration
class CEditBox
{
public:
CEditBox(std::string const&);
private:
std::unique_ptr<CLabel> _label;
};
转发声明避免了包含CLabel.hpp的需要。 unique_ptr
管理生命周期_label
,因此我们不必记住delete
。
//////////// CLabel.hpp header file
#include <string>
#include "CLabel.hpp"
class CLabel
{
public:
CLabel(std::string const& name)
: _name(name)
{
}
private:
std::string _name;
};
只是一个样本,没有什么可看的。让我们继续:
///////////// CEditBox.cpp source file
#include "CEditBox.hpp"
#include "CLabel.hpp"
CEditBox::CEditBox(std::string const& name)
: _label(new CLabel(name))
{
}
这就是魔术:我们通过包含CLabel.hpp来集成它,并在初始化列表中构建它。
///////////// main.cpp source file
#include "CEditBox.hpp"
int main()
{
CEditBox box("Hello world"); // no need to 'know' CLabel here
}
布丁的证明在汇编中: http://ideone.com/zFrJa8
答案 1 :(得分:1)
你的想法是正确的。正确的方法是动态分配这个对象,即
Label = new CLabel;
不要忘记在析构函数中释放内存:
delete Label;
答案 2 :(得分:1)
如果我正确理解你的问题,你有两个类,它们的成员变量是彼此的类吗?
例如:
// A.h
#ifndef A_H
#define A_H
#include "B.h"
class A {
public:
...
private:
B* pB;
};
#endif // A_H
和
// B.h
#ifndef B_H
#define B_H
#include "A.h"
class B {
public:
...
private:
A* pA;
};
#endif // B_H
将这些编译在一起会导致某种形式的链接器错误?如果是这种情况,您可以通过向前声明该类来规避此问题,因此您可以简单地在A.h
和{{B.h
的声明之上写class B;
,而不是包括class A
和class A;
。 1}}在您的class B
声明之上,然后在cpp文件中包含标题。所以A.h
看起来像是:
// A.h
#ifndef A_H
#define A_H
class B;
class A {
public:
...
private:
B* pB;
};
#endif // A_H
答案 3 :(得分:0)
CLabel Field;
应该是CEditBox
的成员。真正的问题是你提到'链接器错误'(或者它是什么)的问题。这是你应该解决的问题。