给C++添加属性机制

    以前用DELPHI和C#时,对DELPHI和C#语法中的属性感到十分方便,在读写属性时能自动调用属性的get, set函数或代码.但我最喜欢的C++中没有属性机制.不过C++提供了范型编程和操作符重载机制,足以让一切变成可能.
    假定要添加属性的类是目标类,给C++添加属性机制,我的想法是建立一个类,重载此类的 "=" 操作符,这样给这个类赋值时,会调用此类的operator = 函数,在此函数中调用目标类的类成员函数即可.但要调用目标类的类成员函数,需要目标类类指针和类成员函数指针.类成员函数指针的类型可以通过模板传入.废话不多说,代码如下:(VC7中编译通过,GCC还未测试)


Property.h

    /*
  by 剑神一笑
  属性定义单元
*/

#ifndef PROPERTY_H
#define PROPERTY_H


//辅助类,用来定义类成员函数指针类型
template<typename T, typename U>
class PropertyType
{
public:
    //指向类成员函数的指针类型
    typedef void (U::*SetProc)(const T&);
    typedef const T& (U::*GetProc)();       
};

//属性基类
template<typename U>
class PropertyBase
{
protected:
    //拥有这个属性的类的指针
    U* obj_;
public:
    void SetObj(U *obj)
    {
        this->obj_ = obj;
    }
};

//只写属性过程定义
template<typename T, typename U, typename PropertyType<T, U>::SetProc Set>
class WriteProperty: public PropertyBase<U>
{
protected:
    //定义属性set的函数指针
    typename PropertyType<T, U>::SetProc SetValue;
public:
    WriteProperty()
    {
        this->SetValue = Set;
    }

    void operator= (const T &value) const
    {
        (obj_->*SetValue)(value);
    }
};

//只读属性过程定义
template<typename T, typename U, typename PropertyType<T, U>::GetProc Get>
class ReadProperty: public PropertyBase<U>
{
private:
    //避免让只读属性可写
    void operator= (const T&) {}
    void operator= (const ReadProperty<T, U, Get>&) {}
protected:
    //定义属性get的函数指针
    typename PropertyType<T, U>::GetProc GetValue;
public:
    ReadProperty()
    {
        this->GetValue = Get;
    }

    operator T() const
    {
        return (obj_->*GetValue)();
    }
};

template<typename T, typename U, typename PropertyType<T, U>::GetProc Get>
std::ostream& operator << (std::ostream &out, const ReadProperty<T, U, Get>& rv)
{
    out << rv.operator T();
    return out;
}

//读写属性过程定义
template<typename T, typename U, typename PropertyType<T, U>::SetProc Set, typename PropertyType<T, U>::GetProc Get>
class ReadWriteProperty: public PropertyBase<U>
{
private:
    typename PropertyType<T, U>::SetProc SetValue;
    typename PropertyType<T, U>::GetProc GetValue;

    //禁用赋值和拷贝构造
    const ReadWriteProperty<T, U, Set, Get>& operator= (const ReadWriteProperty<T, U, Set, Get>&) {}
    ReadWriteProperty(ReadWriteProperty<T, U, Set, Get>&) {}
public:
    ReadWriteProperty()
    {
        SetValue = Set;
        GetValue = Get;
    }

    const ReadWriteProperty<T, U, Set, Get>& operator= (const T &value) const
    {
        (obj_->*SetValue)(value);
        return *this;
    }

    operator T() const
    {
        return (obj_->*GetValue)();
    }
};

template<typename T, typename U, typename PropertyType<T, U>::SetProc Set, typename PropertyType<T, U>::GetProc Get>
std::ostream& operator << (std::ostream &out, const ReadWriteProperty<T, U, Set, Get>& rv)
{
    out << rv.operator T();
    return out;
}

//简化函性定义的宏
//定义读写属性
#define PROPERTY_DECLARE_RW(property_name, type, class_type, set, get) /
    ReadWriteProperty<type, class_type, class_type::set, class_type::get> property_name;
//定义只读属性
#define PROPERTY_DECLARE_R(property_name, type, class_type, get) /
    ReadProperty<type, class_type, class_type::get> property_name;
//定义只写属性
#define PROPERTY_DECLARE_W(property_name, type, class_type, set) /
    WriteProperty<type, class_type, class_type::set> property_name;

#define INIT_PROPERTY(property_name) property_name.SetObj(this);

#endif//PROPERTY_H

//-------------------------华丽的分隔线-----------------------------

测试代码

#include <iostream>
#include <string>
#include "Property.h"

using std::cin;
using std::cout;
using std::string;

class Test
{
private:
    int value_;
    string name_;
public:
    Test(int value)
    {
        INIT_PROPERTY(Value);
        INIT_PROPERTY(Name);
        INIT_PROPERTY(WValue);

        this->value_ = value;
        name_ = "TestClass";
    }

    void SetValue(const int& value)
    {
        cout << "Set Value: " << value << std::endl;
        this->value_ = value;
    }

    const int& GetValue()
    {
        cout << "Get Value: " << value_ << std::endl;
        return value_;
    }

    const string& GetName()
    {
        return name_;
    }

    void ShowValue()
    {
        cout << "Value: " << value_ << std::endl;
    }

    //声明可读写属性,参数为: 属性名,属性类型,当前类名,Set函数,Get函数
    PROPERTY_DECLARE_RW(Value, int, Test, SetValue, GetValue);
    PROPERTY_DECLARE_R(Name, string, Test, GetName);
    PROPERTY_DECLARE_W(WValue, int , Test, SetValue);
};


int main()
{
    Test t(100);
    t.ShowValue();
    t.WValue = 999;            //只写属性可以写入
    //int i = t.WValue;        //只读属性无法读取
    t.Value = 200;            //读写属性可以写入
    int i = t.Value;        //读写属性可以读取
    cout << "i: " << i << std::endl;
    cout << t.Name << std::endl; //只读属性可以读取
    //t.Name = "hello";        //只写属性无法写入
 
    cin.get();
    return 0;
}

运行结果:
Value: 100
Set Value: 999
Set Value: 200
Get Value: 200
i: 200
TestClass

这种方法是类型安全的,但会让目标类占用更多内存,而且属性调用的函数必须为public的,另外为了让属性类能正确的取得目标类类指针,我使用了一个INIT_PROPERTY宏,这样比较麻烦,需要在构造函数中对每个属性调用一下,希望有更好办法的朋友告知.

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: Qt5添加包含QWidget的C++类比较简单。首先,我们需要在头文件(.h)中包含QWidget的声明。例如,我们可以使用以下代码: ```cpp #include <QWidget> ``` 然后,我们可以创建一个新的C++类,并继承自QWidget类。下面是一个示例代码: ```cpp class MyClass : public QWidget { Q_OBJECT public: MyClass(QWidget *parent = nullptr); ~MyClass(); }; ``` 在上述代码中,我们创建了一个名为MyClass的新类,它继承自QWidget。我们还在类的声明中包含了Q_OBJECT宏,这是为了支持Qt的信号和槽机制。 接下来,我们需要实现构造函数和析构函数。这可以在实现文件(.cpp)中完成,如下所示: ```cpp MyClass::MyClass(QWidget *parent) : QWidget(parent) { // 构造函数的实现 } MyClass::~MyClass() { // 析构函数的实现 } ``` 在构造函数中,可以执行初始化操作,例如设置窗口大小、添加控件等。析构函数可以在对象被销毁时执行一些资源清理的操作。 当我们完成上述步骤后,我们就可以在其他地方使用MyClass类了。例如,我们可以在主窗口类中创建一个MyClass的对象,并将它添加到主窗口中: ```cpp MyClass *myObj = new MyClass(this); myObj->show(); ``` 以上就是将包含QWidget的C++添加到Qt5中的基本步骤。当然,在实际开发中可能涉及更多的功能和操作,但基本的原理和方法是相同的。 ### 回答2: 在Qt5中添加一个包含QWidget的C++类可以按照以下步骤进行。 1. 打开Qt Creator,创建一个新的Qt Widgets应用程序项目。 2. 在项目目录中,右键单击项目文件,并选择“添加新建的”>“C++类”。 3. 在弹出的对话框中,输入类的名称,并选择分配给的基类为“QWidget”。 4. 单击“下一步”按钮,选择在哪个目录中生成新类的源文件和头文件。 5. 单击“完成”按钮,Qt Creator自动生成一个新的C++类文件,并将其添加项目中。 现在,您可以使用这个新的QWidget派生类来创建自定义的窗口小部件。您可以在类的头文件中添加任何自定义的成员函数和成员变量,以实现您的应用程序的功能。例如,您可以添加以下内容: ```cpp #ifndef MYWIDGET_H #define MYWIDGET_H #include <QWidget> class MyWidget : public QWidget { Q_OBJECT public: explicit MyWidget(QWidget *parent = nullptr); // 添加自定义成员函数和成员变量 signals: }; #endif // MYWIDGET_H ``` ```cpp #include "mywidget.h" MyWidget::MyWidget(QWidget *parent) : QWidget(parent) { // 在构造函数中进行初始化和设置 } ``` 然后,您可以在主窗口或其他地方创建并使用这个自定义的QWidget派生类: ```cpp #include <QApplication> #include <QWidget> #include "mywidget.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); MyWidget widget; widget.show(); return a.exec(); } ``` 通过以上步骤,您就成功地在Qt5中添加了一个包含QWidget的C++类。您可以根据自己的需求进一步定制和扩展这个类。 ### 回答3: 在Qt5中添加包含QWidget的C++类可以通过以下几个步骤完成。 首先,我们需要创建一个C++类的头文件和源文件。可以使用Qt Creator自动生成这些文件。在Qt Creator中,选择File -> New File or Project,选择C++ Class,并设置类的名称和位置。确保在类的头文件中引入QWidget的头文件,例如#include <QWidget>。 接下来,在类的头文件中,我们需要将该类声明为QWidget的子类。在类的声明中添加一个继承QWidget的关键字: ```cpp class MyClass : public QWidget { Q_OBJECT public: // 类的构造函数和其他成员函数的声明 }; ``` 然后,在类的源文件中,我们需要实现类的构造函数和其他所需的成员函数。可以通过在构造函数中调用QWidget的构造函数来初始化QWidget的实例,并设置类的窗口属性: ```cpp MyClass::MyClass(QWidget *parent) : QWidget(parent) { // 设置窗口属性 setWindowTitle("My Widget"); resize(300, 200); // 其他初始化操作 } ``` 最后,在主程序中,我们可以创建和展示这个自定义的QWidget类的实例。在主函数中创建一个Qt应用程序,然后实例化MyClass类,并显示它: ```cpp int main(int argc, char *argv[]) { QApplication app(argc, argv); MyClass myObject; myObject.show(); return app.exec(); } ``` 通过以上步骤,我们成功地在Qt5中添加了一个包含QWidget的C++类。这个自定义的QWidget类可以通过实例化并显示来在应用程序中使用,并具备QWidget的交互和界面功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值