C++高级 —— 属性

属性

属性(attribute)是C++中用来控制编译器的编译指令。在C++11之前,非标准的实现中已经出现过属性的申请,比如给gnu的__attribute__或者说vc的__declspec

C++11中正式将其纳入标准,其并没有新增关键字,而是采用两对方括号的形式[[...]],中间的…内容就是属性标签。C++中常用的属性标签如下:

  • deprecated:这个指明其修饰的函数是一个已经被抛弃的接口,最好换成新接口。
  • unused:用于变量、类型、函数等,表示其虽然暂时不用,但是最好保留下来。
  • constructor:指明此函数会在main函数之前执行
  • destructor:知名此函数会在main函数之后执行
  • always_inline:要求编译器强制内联函数,inline关键字的加强版
  • hot:标记为热点函数,要求编译器更积极优化

属性Demo

deprecated

我们定义一个函数为deprecated修饰,这会表示这个函数是个旧的接口。

[[gnu::deprecated]]
int old_func()
{
    return 0;
}

int main()
{
    cout << old_func() << endl;
}

编译的时候编译器会报如下的错误:

[ik@localhost test]$ g++ -o test test.cpp
test.cpp: 在函数‘int main()’中:
test.cpp:13:22: 警告:‘int old_func()’ is deprecated [-Wdeprecated-declarations]
     cout << old_func() << endl;
                      ^
test.cpp:6:5: 附注:在此声明
 int old_func()
     ^~~~~~~~

但是运行还是可以正常运行的:

[ik@localhost test]$ ./test
0

unused

这个关键字告诉编译器这个变量我暂时不会用,但是是我故意的,请不要警告我。

[[gnu::unused]] int var;
int main()
{
    return 0;
}

constructor && deconsructor

我们定义两个函数,at_start会在main函数之前执行,at_exit会在main函数之后执行。

[[gnu::constructor]]
int at_start()
{
    printf("excute before main::func\n");
}

[[gnu::destructor]]
int at_exit()
{
    printf("excute after main::func\n");
}
int main()
{
    cout << "main::func excute!" << endl;
    return 0;
}


constructor修饰的函数不能用cout,因为cout需要全局变量初始化!

输出如下:

[ik@localhost test]$ ./test
excute before main::func
main::func excute!
excute after main::fun

always_inline

这个虽然说是可以强制内联,但是编译器可不会管你的。看一下下面的例子:

[[gnu::always_inline]] void func()
{
    printf("i am test_func()");
}

int main()
{
    func();
    return 0;
}
[ik@localhost test]$ g++ -o test test.cpp
test.cpp:3:29: 警告:always_inline function might not be inlinable [-Wattributes]
 [[gnu::always_inline]] void func()
                             ^~~~

参考文献

[1] 罗剑锋.罗剑锋的C++实战笔记.极客时间

C++中实现属性 本文译自http://www.codeguru.com/cpp_mfc/Property.html的Implementing a Property in C++ 以下是译文 本文由Emad Barsoum投稿。 开发测试环境:Visual C++ 7.0, Windows XP sp1, Windows 2000 sp3 摘要 本文试着在C++中不使用任何扩展技术模拟C#(或其他语言)中的属性特征。大多数在C++实现属性的库和编译器使用扩展技术,如Managed C++C++ Builder,或者他们使用如通常函数的set和get方法,但那不是属性。 详述 我们首先看一下什么是属性。一个属性表现为一个字段或者成员变量,但它通过read和write方法或者get和set方法暗中操作变量。 例如,若存在类A和它的属性Count,我可以写如下的代码: A foo; Cout << foo.Count; 实际上Count调用它的get函数返回当前的变量值。你可以将属性定为只读(你可以读取它但不能修改它)、只写或者可读写,这就是使用属性而不直接使用变量的的一个最大好处了。好了,让我们开始来实现它: 我们需要能做如下的事: int i = foo.Count; //--调用get函数得到值 foo.Count = i; //-- 调用set函数设定值 因此,很明显的我们需要重载 = 操作符使其能设定变量的值,同时也要重载该属性的返回值(在下面我们将会看到的)。 我们将实现一个称为property的类,它做的就像一个属性,声明如下: template class property {} 这个模板类表示的是我们的属性。Container是我们要在其中包含属性的类变量,set和get方法以及属性的类的类型。ValueType是内部变量即要定义的属性的类型,nPropType定义属性的读写标志:只读、只写或可读写。 现在我们需要一个指向从包含属性的类Container到属性类property的set和get方法的指针,同时重载 = 操作符以使得属性能象变量起那样作用。现在我们来看property类的全部定义 #define READ_ONLY 1 #define WRITE_ONLY 2 #define READ_WRITE 3 template class property { public: property() { m_cObject = NULL; Set = NULL; Get = NULL; } //-- 将m_cObject指向包含属性的container类 -- void setContainer(Container* cObject) { m_cObject = cObject; } //-- 设定可改变属性值的set成员函数 -- void setter(void (Container::*pSet)(ValueType value)) { if((nPropType == WRITE_ONLY) || (nPropType == READ_WRITE)) Set = pSet; else Set = NULL; } //-- 设定可检索属性值的get成员函数 -- void getter(ValueType (Container::*pGet)()) { if((nPropType == READ_ONLY) || (nPropType == READ_WRITE)) Get = pGet; else Get = NULL; } //-- 重载 = 号操作符使其能用set成员设定属性值-- ValueType operator =(const ValueType& value) { assert(m_cObject != NULL); assert(Set != NULL); (m_cObject->*Set)(value); return value; } //-- 使属性类能转换为内部类型成为可能-- operator ValueType() { assert(m_cObject != NULL); assert(Get != NULL);
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shenmingik

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值