当前位置: 首页 > wzjs >正文

做网站建设公司深圳百度推广电话

做网站建设公司,深圳百度推广电话,如何建学校网站,wordpress数据库文件导入这段内容讲的是C中“属性”(Property)的实现及其设计理念,并结合一个实际类Text来说明。中文理解如下: 关于“属性”(Property) 属性:介于类的字段(field)和方法&#…

这段内容讲的是C++中“属性”(Property)的实现及其设计理念,并结合一个实际类Text来说明。中文理解如下:

关于“属性”(Property)

  • 属性:介于类的字段(field)和方法(method)之间的东西。
    也就是说,属性看起来像成员变量,但可以通过方法(getter/setter)控制访问和赋值,实现更灵活的封装和控制。

代码示例类 Text

class Text : public BaseElement
{
public:ZOBJ(Text);                   // 可能是宏定义,做一些元编程的辅助Text() : string(nullptr) { }  // 构造函数,初始化 string 为 nullptrint align;                    // 对齐方式,属性示例之一ZString *string;              // 字符串指针int stringLength;             // 字符串长度float drawOffsetY;            // 绘制时的Y轴偏移FontGeneric *font;            // 字体对象指针float wrapWidth;              // 自动换行宽度DynamicArray *formattedStrings; // 格式化字符串数组DynamicArray *multiDrawers;   // 多重绘制器float maxHeight;              // 最大高度bool wrapLongWords;           // 是否允许长词换行virtual Text *initWithFont(FontGeneric *i);  // 初始化方法...
};

理解总结

  • 这个类中列出了一些“属性”字段,比如alignstringwrapWidth等。
  • 这些“属性”很直观地是类的数据成员,但实际项目中,想把这些直接字段换成属性(比如封装成getter/setter)可以增强安全性和灵活性。
  • 这正是“属性”的本质:外观是数据成员,但实际上是通过方法控制访问的接口。
  • 你可以用类似C#的属性语法来模拟,或者用宏/模板等方式来简化写法。

这段代码体现了大量遗留代码(legacy code)的实际用法和风格,中文理解如下:

代码分析

Text* text;
...
text->setText(ZS(STR_LOC_OMNOM));
...
text->width = 42;
text->height = GetQuadOffset(IMG_OMNOM__top_offs).y;
...
text->draw();

理解总结

  • text 是指向 Text 类实例的指针。
  • text->setText(ZS(STR_LOC_OMNOM));
    这是通过方法(setter)设置文本内容,ZS(STR_LOC_OMNOM) 可能是某种字符串宏或转换函数。
  • text->width = 42;text->height = ...;
    直接通过公有成员变量访问和赋值宽高。
    这里是“直接访问字段”的风格,缺乏封装性和安全性。
  • text->draw();
    调用对象的方法进行绘制。

说明

  • 这种混合用法:部分用方法访问(setText()),部分直接访问字段(width, height)是典型的遗留代码风格。
  • 直接字段访问容易导致难以控制属性的变化,也难以插入额外逻辑(如验证、事件通知等)。
  • 这也是为什么现代代码倾向于将“属性”封装为 getter/setter 或类似机制。

1. 需求背景

想模拟C#里“属性”(Property)的语法:

foo.size = 10; // 实际调用setter
int x = foo.size; // 实际调用getter

而不是直接访问成员变量。

2. 最简单的实现——成员变量直接暴露

class Bar {
public:int size;
};

用法:

Bar bar;
bar.size = 10;  // 直接赋值成员变量

缺点:不能拦截赋值或读取操作,无法封装额外逻辑(例如校验、触发事件等)。

3. 用getter/setter封装访问

class Foo {
private:int size;
public:void setSize(const int& s) { size = s; }const int& getSize() const { return size; }
};

用法:

Foo foo;
foo.setSize(10);       // 设置
int x = foo.getSize(); // 读取

缺点:调用写法不够简洁。

4. Property模板类模拟属性语法糖

想实现:

foo.size = 10;  // 自动调用setSize
int x = foo.size; // 自动调用getSize

这需要通过C++运算符重载和隐式类型转换来实现。

5. 纯存储型Property(不满足调用宿主方法需求)

template<typename T>
class Property {
private:T value;
public:Property<T>& operator=(const T& v) {value = v;return *this;}operator const T&() {return value;}
};
  • 赋值重载=operator=,赋值给内部成员
  • 隐式转换operator T&(),读取时返回内部成员引用
    缺点
  • 不能调用宿主对象的方法,不能实现额外逻辑。

6. 用std::function封装getter/setter,满足调用宿主函数需求

template<typename T>
class Property {
private:std::function<void(const T&)> setter;std::function<const T&()> getter;
public:Property(std::function<void(const T&)> s, std::function<const T&()> g): setter(s), getter(g) {}Property<T>& operator=(const T& v) {setter(v);return *this;}operator const T&() {return getter();}
};

用法示例:

class Test {
private:float dimension;
public:const float& getArea() const {// 假设返回引用可能不安全,这里简化示例static float area = dimension * dimension;return area;}void setArea(const float& val) {dimension = std::sqrt(val);}Property<float> area;Test() : area([this](const float& v){ setArea(v); },[this]() -> const float& { return getArea(); }) {}
};
  • Property对象内部保存两个std::function,指向宿主对象的方法。
  • 赋值时调用setter,读取时调用getter。

缺点

  • std::function内部存储函数对象(闭包),开销较大,至少有堆分配和类型擦除,sizeof(Property)通常较大(例如32字节)。
  • 每次调用通过std::function间接,性能下降。

7. 用成员函数指针(member function pointers)优化

成员函数指针示例:

struct Test {void setVal(const int& v) { /* ... */ }const int& getVal() const { /* ... */ return val; }int val;
};
  • 成员函数指针类型:
    • void (Test::*)(const int&) ——指向成员函数void setVal(const int&)
    • const int& (Test::*)() const ——指向成员函数const int& getVal() const

8. 结合成员函数指针写Property模板

template <typename T, typename Host>
class Property {
private:void (Host::*setter)(const T&);const T& (Host::*getter)() const;Host* host;
public:Property(void (Host::*set)(const T&), const T& (Host::*get)() const, Host* h): setter(set), getter(get), host(h) {}Property<T, Host>& operator=(const T& value) {(host->*setter)(value);  // 调用宿主setterreturn *this;}operator const T&() const {return (host->*getter)(); // 调用宿主getter}
};

优点:

  • Property对象只存储3个指针(setter、getter成员函数指针 + 指向宿主实例的指针),通常24字节。
  • std::function轻量许多。
  • 调用时通过成员函数指针调用宿主函数,调用开销更低。

缺点:

  • 调用时仍有两次间接调用:
    • host->*setter,调用成员函数指针;
    • 成员函数调用本身也有一定调用开销(尤其虚函数)。

9. 进一步优化思考:利用成员指针偏移

成员指针本质上是宿主类对象中某成员的偏移(对数据成员而言),或成员函数的地址。
如果只操作数据成员(不是调用函数),我们可以将“成员指针”当做偏移量,在编译期知道偏移量,直接用指针+偏移访问成员数据。
比如:

template<typename T, typename Host, T Host::*member>
class Property {
private:Host* host;
public:Property(Host* h) : host(h) {}Property<T, Host, member>& operator=(const T& value) {host->*member = value;  // 直接访问成员变量return *this;}operator const T&() const {return host->*member;   // 直接访问成员变量}
};

10. 将“调用宿主方法”的逻辑加入

如果你想要“赋值时调用宿主的setter函数”,读取时调用getter函数,而不直接访问成员变量,需要你在Host类中写统一的接口,比如:

struct Foo {int size_;void setSize(const int& v) { size_ = v; }const int& getSize() const { return size_; }
};

配合:

template<typename T, typename Host, T Host::*member>
class Property {
private:Host* host;
public:Property(Host* h) : host(h) {}Property<T, Host, member>& operator=(const T& value) {host->setSize(value);  // 这里硬编码了setSize,不能通用return *this;}operator const T&() const {return host->getSize();}
};

但这显然不通用,也不能自动匹配getter/setter,除非借助宏或者模板技巧(如成员函数指针传参)。

11. 性能对比总结

方案内存大小(示例)调用层数优点缺点
纯成员变量sizeof(T)0简单快速不能调用getter/setter
Property + std::function~32字节3灵活,可任意函数封装大开销,调用慢
Property + 成员函数指针~24字节2较轻量,调用宿主函数调用间接层依旧存在
Property + 成员变量指针(偏移)~8字节1轻量,调用快只能直接访问数据成员

12. 实际应用示例

struct Foo {int size_;void setSize(const int& v) { size_ = v; }const int& getSize() const { return size_; }
};
template<typename T, typename Host>
class Property {
private:void (Host::*setter)(const T&);const T& (Host::*getter)() const;Host* host;
public:Property(void (Host::*set)(const T&), const T& (Host::*get)() const, Host* h): setter(set), getter(get), host(h) {}Property<T, Host>& operator=(const T& value) {(host->*setter)(value);return *this;}operator const T&() const {return (host->*getter)();}
};
int main() {Foo foo;Property<int, Foo> sizeProp(&Foo::setSize, &Foo::getSize, &foo);sizeProp = 10;               // 调用foo.setSize(10)std::cout << int(sizeProp); // 调用foo.getSize()
}

13. 总结

  • 模拟属性的最佳方案取决于效率与灵活性的权衡:
    • 最高效的是直接数据成员指针操作,但无法封装逻辑。
    • 最灵活的是std::function,但内存占用和运行时开销大。
    • 成员函数指针折中方案较常用,性能和灵活性都较好。
  • C++目前没有原生支持属性语法,只能靠重载运算符模拟。
  • 你若追求最高效率,可以用模板配合成员指针偏移和宿主类接口,消除动态调用。
http://www.dtcms.com/wzjs/56702.html

相关文章:

  • 为什么我自己做的网站百度不到百度网站检测
  • 怎么自己做网站版面设计目前常用的搜索引擎有哪些
  • 自己怎么做网站购买空间教育机构退费纠纷找谁
  • 二手车东莞网站建设建个网站需要多少钱?
  • 苏州做网站的网络公司诈骗百度账号免费注册
  • 武汉个人做网站联系电话seo关键词排名
  • 建设部网站官网考试长沙网站seo报价
  • dw做的网站怎么去掉谷歌推广怎么样
  • 可以做网站的公司有哪些网站权重查询
  • 武汉前端网站开发公司如何提高自己的营销能力
  • 提供网站建设工具的品牌网站站点
  • 电子商务网站的建设报告新浪博客seo
  • 静态网站论文目录市场营销策略包括哪些策略
  • 建设干部培训中心网站网站优化检测
  • 合肥公司网站建设seo 怎么做到百度首页
  • 温州seo网站建设代推广平台
  • discuz品牌空间网站百度账号登录官网
  • 做网站时,404网页如何指向世界疫情最新数据
  • 阳谷聊城网站优化泰州网站建设优化
  • 上海网站建设服务站霸网络基本营销策略有哪些
  • 长沙征帆网站建设长沙seo霜天博客
  • 浉河网站建设网络营销乐云seo
  • 腾讯云主机做网站竹子建站官网
  • 崇信县门户网站最新留言推广普通话手抄报模板可打印
  • 山西省疫情最新情况夜狼seo
  • 做网站的调查问卷seo免费入门教程
  • 住宅城乡建设部门户网站关键词的优化方法
  • 婚姻咨询律师在线页面优化的方法
  • 注册网站乱填邮箱seo站点
  • 嘉兴网站快速排名优化注册域名在哪里注册