热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C++中final类的实现

namespacePrivate{classNonDerivableHelper{NonDerivableHelper(){}friendclassNonDeri

namespace   Private{ 
class NonDerivableHelper
{
NonDerivableHelper() {}
friend class NonDerivable;
};
}
#ifdef NDEBUG
#define FINAL_CLASS
#else
#define FINAL_CLASS : private virtual Private::NonDerivableHelper
#endif
class NonDerivable FINAL_CLASS
{
...
};


在《C++ View》第一期P25,《C++中常用的几个小技巧》中,提供了实现final类的方法。
这里我们先不将方法写全,而是抽取其中精华的部分来看。
     在看代码之前,首先我们要了解的知识包括,构造函数,私有访问,友元,私有继承,虚拟继承,以及虚拟继承下的特殊初始化语义(虚拟基类的初始化变成了最终派生类的责任)。
这些可以参考《C++ Primer》第三版中的相关内容,因为内容较多,需要整理一下,再行发出。
1.构造函数                                              


     在《C++ View》第一期P25,《C++中常用的几个小技巧》中,提供了实现final类的方法。
这里我们先不将方法写全,而是抽取其中精华的部分来看。

     在看代码之前,首先我们要了解的知识包括,构造函数,私有访问,友元,私有继承,虚拟继承,以及虚拟继承下的特殊初始化语义(虚拟基类的初始化变成了最终派生类的责任)。
这些可以参考《C++ Primer》第三版中的相关内容,因为内容较多,需要整理一下,再行发出。
1.构造函数                                               -----       待整理
2.私有访问                                               -----       待整理
3.友元                                                      -----       待整理
4.私有继承
         private继承是因为父类提供了更多的接口,而子类并不需要这些接口来对外,子类只是在提供自己接口的时候,希望重用父类的实现。从而private继承父类,这样父类的公有方法在子类中全部成为了private方法,只有子类的成员函数和友元类可以访问这些方法,而其他使用均为非法。
5.虚拟继承                                               -----       待整理
6.虚拟继承下的特殊初始化语义               -----       待整理

所有代码均为完整代码,非代码片段,可以直接使用;所有代码均经过测试,测试平台VS2005。
一些代码不能编译通过,正是说明了语言特性,请联系上下文使用代码。
代码1:

#include 
using namespace std;

class NonDerivableHelper
{
private:
NonDerivableHelper()
{
cout<<"base1"<}
friend class NonDerivable;
};
class NonDerivable:private NonDerivableHelper
{
public:
NonDerivable():NonDerivableHelper()
{
cout<<"base2"<}
};

class Derive:public NonDerivable{
public:
Derive():NonDerivable()
{
cout<<"Derive"<}
};
int main()
{
Derive d;
return 1;
}

代码1中Derive类可以继承NonDrivable类,NonDerivable类可以使用NonDerivableHelper的私有

构造函数方法(因为NonDerivableHelper类声明NonDerivable类为其友元)。从而可以继承成功。

代码2:

#include 
using namespace std;

class NonDerivableHelper
{
private:
NonDerivableHelper()
{
cout<<"base1"<}
friend class NonDerivable;
};
class NonDerivable:private virtual NonDerivableHelper
{
public:
NonDerivable():NonDerivableHelper()
{
cout<<"base2"<}
};

class Derive:public NonDerivable{
public:
Derive():NonDerivable()
{
cout<<"Derive"<}
};
int main()
{
Derive d;

return 1;
}


在11行的类继承时,加上virtual继承,这样Derive类就无法再对NonDerivable类进行继承了,NonDerivable

即我们所要实现的final类。会在编译时出现错误。这时的疑问就是,无论如何都会出现无法继承吗?
OK,第一种情况:Derive类自己不实现构造函数,使用默认的构造函数。
代码3:
#include 
using namespace std;

class NonDerivableHelper
{
private:
NonDerivableHelper()
{
cout<<"base1"<}
friend class NonDerivable;
};
class NonDerivable:private virtual NonDerivableHelper
{
public:
NonDerivable():NonDerivableHelper()
{
cout<<"base2"<}
};

class Derive:public NonDerivable{
public:
};
int main()
{
Derive d;

return 1;
}

这时我们编译发现,还是编译错误:cannot access private member declared in class 'NonDerivableHelper'
说明默认还是去调用了基类的构造函数。
第二种情况:
NonDerivable类也不去实现构造函数而使用默认构造函数。
代码4:
#include 
using namespace std;

class NonDerivableHelper
{
private:
NonDerivableHelper()
{
cout<<"base1"<}
friend class NonDerivable;
};
class NonDerivable:private virtual NonDerivableHelper
{
public:

};

class Derive:public NonDerivable{
public:

};
int main()
{
Derive d;

return 1;
}

这时也会发现,同样的编译错误。
说明Derive类不是通过NonDerivable类来调用的基类的构造函数。
第三种情况,将NonDerivableHelper中的friend class NonDerivable的友元声明去掉。
代码5:
#include 
using namespace std;

class NonDerivableHelper
{
private:
NonDerivableHelper()
{
cout<<"base1"<}
};
class NonDerivable:private virtual NonDerivableHelper
{
public:

};

class Derive:public NonDerivable{
public:

};
int main()
{
Derive d;

return 1;
}


这时还是和上面报的一样的错误。Derive不能访问基类的private方法。
第四种情况:将NonDerivableHelper中的friend class NonDerivable的友元声明去掉。将NonDerivable
的继承修改为private继承。

代码6:

这时我们发现,编译错误改变了,现在是NonDerivable类不能访问NonDerivableHelper类的private
构造函数了。这也是正确的,因为只有该类的友元与该类的成员函数可以访问private成员,而子类是不
可以的。
这个例子与下面的相同:
1 #include   
2 using namespace std;
3
4 class NonDerivableHelper
5 {
6 private:
7 NonDerivableHelper() {cout<<"Base1"< 8 friend class NonDerivable;
9 };
10
11 class NonDerivable:private NonDerivableHelper
12 {
13 private:
14 NonDerivable() {}
15 };
16
17 class Derive:public NonDerivable
18 {
19
20 };
21
22 int main()
23 {
24 Derive d;
25 }

此时,编译错误。Derive不能够访问父类NonDerivable的对象。
从上面的代码可以了解virtual继承,private访问控制,友元的一些关系。

推荐阅读
  • 对象内存地址
    主  题 ... [详细]
  • 首先说一下,这是我在CSDN上的第一个文章,其实这个账号早在几年前就申请了,不过当时只是为了下载一个资源,而且也不怎么懂信息技术相关的领域,后来就再也没怎么动过,直到今天我才开始使用这个账号 ... [详细]
  • 本文探讨了一个在Mac Mavericks系统上使用Clang++成功编译但通过R CMD SHLIB构建并在R中加载时遇到‘符号未找到’错误的C++程序问题。文章详细分析了错误原因,并提供了有效的解决方案。 ... [详细]
  • 深入解析C++ Atomic编程中的内存顺序
    在多线程环境中,为了防止多个线程同时修改同一数据导致的竞争条件,通常会使用内核级同步对象,如事件、互斥锁和信号量等。然而,这些方法往往伴随着高昂的上下文切换成本。本文将探讨如何利用C++11中的原子操作和内存顺序来优化多线程编程,减少不必要的开销。 ... [详细]
  • 第五周项目一——体验常成员函数(1)
    设计平面坐标点类,计算两点之间距离、到原点距离、关于坐标轴和原点的对称点等。在设计中,由于求距离、求对称点等操作对原对象不能造成任何改变,所以,将这些函数设计为常成员函数是合适的,能够避免数据成 ... [详细]
  • ProblemDescriptionAninchwormisatthebottomofawellninchesdeep.Ithasenoughene ... [详细]
  • 第3章 感受(一)——3.1. Hello world 经典版
    [回到目录]白话C++第3章.感受Helloworld!,HelloC++,我们来了!3.1.Helloworld经典版毫无疑义,一 ... [详细]
  • CC++如何复制 ... [详细]
  • 下面想跟大家分享一下,请大家看下面一个例子,看看结果是什么?#include<iostream>usingnamespacestd;intmain() ... [详细]
  • 本文介绍了几种不同的编程方法来计算从1到n的自然数之和,包括循环、递归、面向对象以及模板元编程等技术。每种方法都有其特点和适用场景。 ... [详细]
  • 结构体在内存中的对齐规则
    一个结构体变量定义完之后,其在内存中的存储并不等于其所包含元素的宽度之和。例一:#include<iostream ... [详细]
  • 要求:海伦公式:ssqrt(p*(p-a)*(p-b*)(p-c)),其中p(a+b+c)2,a,b,c为三角形的三个边。定义两个带参数的宏,一个用来求p,另一个用来求s题目分 ... [详细]
  • 题目:poj2342Anniversaryparty题意:话说一个公司的一些然要去参加一个party,每个人有一个愉悦值,而如果某个人的直接上司在场的话会非常扫兴,所以避免这样 ... [详细]
  • 名字空间是为了防止名字污染在标准C++中引入的。它可以将其中定义的名字隐藏起来,不同的名字空间中可以有相同的名字而互不干扰,使用时用域操作符(::)来引用。namespace名字{ ... [详细]
  • #include<iostream>usingnamespacestd;#defineN4charboard[N][N];intcol[N]; ... [详细]
author-avatar
BLUE1352_126
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有