首页 > 编程语言 >c++ 静态成员的初始化 友元模板

c++ 静态成员的初始化 友元模板

时间:2024-06-07 17:34:12浏览次数:25  
标签:友元 初始化 调用 静态 成员 c++ Init static 模板

 

来自:https://www.cnblogs.com/fre2technic/archive/2011/03/25/1995044.html

 

我们定义如下类:

复制代码 //A.h
class A
{
private:
    static const int m = 5;
    static int n;
    static vector<int> buf;
}; 复制代码

其中包含三个私有的静态类成员,C++规定const静态类成员可以直接初始化,其他非const的静态类成员需要在类声明以外初始化,我们一般选择在类的实现文件中初始化,初始化的方式是书写一遍类型的定义:

//A.cpp
int A::n;                 //不指定任何初始值,系统自动初始化为0
vector<int> A::buf;       //调用vector的默认构造函数来初始化
                            //注意:调用默认构造函数时,不要使用括号,否则编译器将把A::buf()当做静态成员函数,
                            //但是A::buf()实际没有被声明,所以编译器将报错

 或者:

//A.cpp
int A::n(9);              //使用字面量9来初始化n
vector<int> A::buf(100);  //调用vector的带参构造函数来初始化

 

对于更复杂的情形 ,如没有构造函数可以调用(比如单例模式实现的类),或者需要多步骤才能完成的初始化怎么办?
假设有一个类S实现了单例模式,S的实例是通过调用S的静态方法S::GetInstance()来获得的,现在定义一个包含S作为静态成员的类:

//B.h
class B
{
private:
    static S s;
};

 按照前面的介绍,我们或许应该以下面这种方式初始化s:

//B.cpp
#include <B.h>
S B::s;  //编译器会报错,因为S没有可以调用的构造函数

 解决方法是定义一个静态方法,负责初始化静态成员s:

复制代码 //B.h
class B
{
public:
    static S Init();
private:
    static S s;
};

//B.cpp
#include <B.h>
S B::Init()
{
    ....
    return S::Instance();
}
S B::s = B::Init();            //调用静态函数初始化静态成员 复制代码

 

上例中,为了初始化类B的静态 成员s,我们定义了一个公有的静态方法Init(),它可以很好的工作。但是,在现实的工程中,我们很可能碰到更进一步的要求,就是希望Init()仅仅作为静态变量s的初始化器使用,而不能使用在程序中别的地方,但是我们又不能把Init()声明为private,这样Init()就不能被调用来初始化s了。解决的方法是使用内部类:

//B.h class B
{
private:
    class C
    {
    public:
        static S InitB();
    };
    static S s;
};

//B.cpp
S B::C::InitB()
{
    ....
    return S::Instance();
}
S B::s = B::C::InitB();         //调用内部类的静态成员函数来初始化静态数据成员  

因为C是B的内部类,C仅在B的作用域范围内可见,如果程序的其他地方调用了B::C::InitB(),编译器将报错,因为C不可访问。 

 

最后说一下,从初始化的方式可以看出来,类的静态数据成员其实就是“带类名”的全局变量。

静态数据成员必须显式初始化,否则在类方法中操作该成员时,将报链接错误 undefined reference to `A::buf' (gcc中)

 

https://www.cnblogs.com/fre2technic/archive/2011/03/25/1995044.html

 

===========

 

===========

 

 

参考:

 

标签:友元,初始化,调用,静态,成员,c++,Init,static,模板
From: https://www.cnblogs.com/rebrobot/p/18237596

相关文章

  • C++数据结构之:哈希表Hash
    摘要:  it人员无论是使用哪种高级语言开发东东,想要更高效有层次的开发程序的话都躲不开三件套:数据结构,算法和设计模式。数据结构是相互之间存在一种或多种特定关系的数据元素的集合,即带“结构”的数据元素的集合,“结构”就是指数据元素之间存在的关系,分为逻辑结构和存储......
  • C++数据结构之:图Graph
    摘要:  it人员无论是使用哪种高级语言开发东东,想要更高效有层次的开发程序的话都躲不开三件套:数据结构,算法和设计模式。数据结构是相互之间存在一种或多种特定关系的数据元素的集合,即带“结构”的数据元素的集合,“结构”就是指数据元素之间存在的关系,分为逻辑结构和存储结......
  • C/C++ 联合体的注意事项
    联合体(Union)在C/C++中是一个特殊的数据类型,它允许在相同的内存位置存储不同的数据类型。联合体的主要特点是,其所有的成员共享同一块内存区域,也就是说,联合体中的各个成员首地址都是相同的。这使得联合体在节省内存、进行数据类型转换等方面非常有用。然而,使用联合体时也需要注意......
  • C++ 模板
    一.非类型模板参数模板参数分为类型形参与非类型形参。类型形参:类作为模板参数,typename/classT(T就是类型形参)非类型形参:内置类型作为模板参数,intdoublechar...(在C++20前只有int可以传)这样我们就可以随便定义栈的大小。注:因为n是常量所以是不能修改的。......
  • 免费,C++蓝桥杯比赛历年真题--第14届蓝桥杯省赛真题(含答案解析和代码)
    C++蓝桥杯比赛历年真题–第14届蓝桥杯省赛真题一、选择题答案:A解析:C++中bool类型与char类型一样,都需要1byte。一些其他类型的占用字节数:short:2byte,int:4byte,longlong:8byte,double:8byte,故答案为A。答案:C解析:A中结构体中可以定义成员变量,也可以定义只有该结......
  • 10_1、C++继承与派生:声明与继承关系
    声明与继承关系继承派生概念派生类声明派生类从基类继承的过程吸收基类成员修改基类成员添加新成员继承关系公有继承保护继承私有继承继承派生概念类的继承就是新类由已经存在的类获得已有特性。类的派生则是由已经存在的类产生新类的过程。由已有类产生新类时,新......
  • 自媒体必用的50 个最佳 ChatGPT 社交媒体帖子提示prompt通用模板教程
    在这个信息爆炸的时代,社交媒体已经成为我们生活中不可或缺的一部分。无论是品牌宣传、个人展示,还是日常交流,我们都离不开它。然而,要在众多信息中脱颖而出,吸引大家的关注并不容易。这时候,ChatGPT这样的AI写作工具就显得特别有用了。ChatGPT不仅能帮你快速生成高质量的内容,还能给你......
  • 【NOI】C++程序结构入门之循环结构二-for循环
    文章目录前言一、for循环1.导入2.语法3.使用场景4.条件控制5.小结二、例题讲解问题:1264-4位反序数问题:1085-寻找雷劈数问题:1057-能被5整除且至少有一位数字是5的所有整数的个数问题:1392-回文偶数?问题:1090-同因查找问题:1446.人口增长问题三、总结四、感谢......
  • C++ -- 引用
    什么是引用?引用其实就是一个变量的别名。也就是说,你可以通过引用的名称去访问原来的那个变量。其操作符很简单,就是在变量前面加上&。一个很简单的例子://variableinti;//referencevariablesint&r=i;i=5;cout<<"valueofiis:"<<i<<endl;......
  • C++11原子操作
    目录1.什么是原子操作2.为什么需要原子操作?3.C++中的原子操作4.原子操作使用及注意5.应用场景6.使用原子操作的最佳实践7.原子操作与锁机制的比较8.总结1.什么是原子操作        原子操作是一种不可分割的操作,即在多线程环境中,这些操作要么全部执行完成,要么......