C++ static const friend virtual inline学习总结

参考:https://www.cnblogs.com/houjun/p/4910811.html
static 的作用:
(1) 隐藏.使得全局变量和函数对其他文件不可见,同时避免了不同文件的命名冲突
(2) 默认初始化为0.未初始化的全局静态变量和局部静态变量都保存在BBS段,BBS段的特点是,程序运行之前会自动清零。
(3) 保持局部变量内容的持久性。此变量声明周期是整个程序的声明周期,但是作用域只在声明它的函数中。

类中的static,表示属于某个类单数不属于类的任何特定对象的变量和函数。
1)对于类的静态数据成员:
a、类的静态数据成员独立于该类的任意对象而存在;其值的修改被类的所有对象看见。
b、static数据成员必须在类定义的外部定义,通常放在包含类的非内联成员函数定义的文件中。
c、但是也有例外,const static 数据成员可以在类的定义体中进行初始化,因为const定义时必须初始化。

2)对于类的成员函数:
a、static成员函数由于不与任何对象关联,因此它不具备this指针,因此,它无法访问属于类对象的非静态数据成员,也无法访问
非静态成员函数。也就是说,类的静态成员函数,只能调用该类的其它静态成员函数和静态数据成员。
b、static成员不是任何对象的组成部分,所以成员函数不能被声明为const。此外,static成员函数也不可以声明为virtual,volatile。
关于静态成员函数的总结:
(1)静态成员之间可以相互访问,不能访问非静态成员。非静态成员函数可以任意访问静态和非静态成员。
(2)静态函数执行速度比非静态函数稍快。

const:
1、const定义后就不能修改,因此定义时要初始化。

2、在C语言中
const buffsize = 10;
int buf[buffsize];
是错误的;
而在C++中是正确的。C中改为const int buffsize;

3、使用const比使用#define有更多的优点:
1)const常量有数据类型,而宏常量没有。前者可以进行类型安全检查,而后者只是进行简单的字符替换。
2)使用const可能比#define得到更小的目标代码,因为替换可能会是同一变量在不同的地方有多个备份。
3)const执行常量折叠,编译时可以把一个复杂的常量表达缩减成简单的。
总之,我们建议使用const替换#define

4、指针和const修饰符:
记住以下一个规则就足够了,即以’*'为分界,左边是对象,右边是指针。
1)const在左边表示指针指向const对象,指针可变,对象不可变。 const *a: a可变, * a 不可变
2)const在右边表示const指针,指针不可修改,对象可以修改。 * const a:

5、const修饰函数参数
1)const形参可以接受非const实参,但是非const形参不兼容const实参。因此,我们为了避免这种问题,尽量使用const修饰形参。
2)由于gcc下,临时对象是const类型,基于1),形参必须声明为const类型,否则出错。

6、const在类中的应用
1)this指针是const,假设base是一个类,这 base *const this;
2)而const修饰的成员函数,其this指针指向的是一个const对象,即 const base *const this;const成员函数不能修改调用该函数的对象。
3)非const对象,既可以调用const成员函数,也可以调用非const成员函数;而const对象,只能调用const成员函数。
4)const数据成员,必须在构造函数的成员初始化列表中进行初始化。

7、关于C++中,static、const以及static,const成员变量的初始化:
在C++中,static成员变量只能在类的内部声明不能再类内部进行初始化,通常在类的实现文件中初始化,static关键字只能用于类定义体内部声明中,定义时不能标示为static。
在C++中,const成员变量也不能再类定义处初始化,只能通过构造函数初始化列表进行,并且必须有构造函数。const数据成员只在某个对象声明周期内是常量,而对于整个类而言,确实可变的。因为类可以创建多个对象,不同对象其const数据成员的值可以不同,所以不能再类声明中初始化const数据成员,因为对象没有被创建,编译器不知道const数据成员的值是什么。
const数据成员的初始化只能在类的构造函数的初始化列表中进行,想要建立整个类中都恒定的常量,应该用类中的枚举常量来实现,或者static const 。

static 成员函数不能访问非static成员变量,可以访问static成员变量
非static函数可以访问static 非static成员变量
参考:https://www.cnblogs.com/rickyk/p/4238380.html
staitc 成员函数访问非静态成员的几种方法:
方法一:有一个很取巧的办法,就是在静态函数的形参表里加上实例的地址,也就是

class A
{
public:
    static void test(A *a)
    {
        a->m_a += 1;
    }
    void hello()
    {
    }
private:
    static int m_staticA;
    int m_a
};

这样在你回调函数的时候,你可以通过这个来让本身不能访问成员非静态变量的静态函数 来访问非静态成员变量。

方法二:
其实这个方法在GLIB中用的很多,就是放上全局变量地址即

A g_a;

class A
{
public:
    static void test()
    {
        g_a.m_a += 1;
    }
    void hello()
    {
    }
private:
    static int m_staticA;
    int m_a
};

方法三:
大家都知道静态成员函数不能访问非静态成员,但别忘了,他们可以访问静态成员,也就是说,如果我们的这个类是个单例,我们完全可以在创建的时候把this指针赋值给那个静态成员,然后在静态成员函数内部就可以放心大胆的使用了。

class A
{
public:
    A()
    {
        m_gA = this;
    }
    static void test()
    {
        m_gA.m_a += 1;
    }
    void hello()
    {
    }
private:
    static int m_staticA;
    static A *m_gA;
    int m_a
};

方法四:
和方法一比较像,但他的方向思想更多的是针对内存块这个概念,意思就是在静态函数的形参比加上一个void *的内存首地址,然后在内部做转换

class A
{
public:
    static void test(void *pData)
    {
        A *a = (A *)pData;
        a->m_a += 1;
    }
    void hello()
    {
    }
private:
    static int m_staticA;
    int m_a
};

A a;
test(&a);

class内部可以初始化:
static const int i=10;
static int a;没有const的情况下只能定义不能赋值初始化;初始化可以在构造函数中初始化,也可以在函数外直接赋值操作
const int b=6;//const 成员变量可以直接初始化赋值
const int c;//如果只是申明的情况下,在构造函数中初始化

static string name="xiaoming";//全局变量可以在类外部直接赋值初始化操作,默认是static的
int goods=11;//全局变量默认是static的

class A;
class B
{
public:
    B(){};
    ~B(){};
public:
    void setage(int x,A &a); //这里友元类,友元成员函数公用了,如果是友元函数可以在class外部用void B::setage(int x,A &a)实现
//    {
//        a.age=x;
//        cout<<"friend B age=="<<a.age<<endl;
//    }
};

class A
{
public:
    //给const 变量zz赋值
    A(int i):zz(i){
    cout<<"构造函数"<<endl;
};
    ~A()
    {
        cout<<"A 析构函数"<<endl;
    }
public:
    //class内部函数调用函数的私有比那辆
    void say(string str)
    {
        cout<<"my name is "<<str<<endl;
    }
    void putnum()
    {
        cout<<"oo == "<<oo<<endl;
        cout<<"zz == "<<zz<<endl;
        cout<<"xx == "<<xx<<endl;
        cout<<"yy == "<<yy<<endl;
    }
    string getname()
    {
        return this->name;
    }
    //私有变量赋值
    void setname(string str)
    {
        this->name=str;
    }
public:
    //友元函数声明
    friend void setage1(int x,A &a);
    friend class B;//友元类声明
    friend void B::setage(int x,A &a);//友元函数声明

public:
    int age;

private:
    string name;
    static int xx;//static 变量只能在类内部定义,这样声明后,分配的内存地址是不变的,其内容可以改变,一个地方改变了,其值就改变了 static成员变量无论你创建多少个对象都只有唯一的一个版本.普通成员变量你创建一个对象就有一个副本
    static const int yy=5;//const 变量可以在class内部赋值初始化
    const int zz;
    const int oo=11;//const 变量可以在class内部初始化  (有些地方说不能呢这样初始化的,但是我的程序可以编译运行)
};

//A::A() {
//    cout<<"A 构造函数"<<endl;
//}

友元函数实现
//void setage1(int x,A &a)
//{
//    a.age=x;
//    cout<<"friend function age=="<<a.age<<endl;
//}

//友元函数实现
void B::setage(int x,A &a)
{
    a.age=x;
    cout<<"friend function age=="<<a.age<<endl;
}

//在类外定义并初始化,不必再加static关键字
int A::xx=7;
int main()
{
//    A a;
    A a(9);
    B b;
//    a.setage1(18,a);
    a.putnum();
    a.say(name);
    a.setname("hello");
    cout<<a.getname()<<endl;

    b.setage(11,a);//
    return 0;
}

友元类:可参考https://www.cnblogs.com/zhuguanhao/p/6286145.html

virtual 函数是用于函数的重写的,普通函数只能被重载,虚函数运行时才能被动态绑定.
inline 内联函数是为了在代码中直接展开,提高程序的运行效率,可以访问程序的所有私有成员变量及函数,当内联函数过于复杂的时候,可能会被编译器拒绝.

为什么c++不支持静态成员函数为虚函数:
静态成员函数对于每一个类来说只有一份,所有对象都共享这一份代码,他也没有动态绑定的必要性.
没有继承特性的函数就没有虚函数的说法

static函数不能被继承,只属于该类.
友元函数不属于类的成员函数,不能被继承
inline是程序被编译时就展开
virtual:是程序运行期才能确定如何去调用的,一切virtual函数都不可能是inline的

c++ 类中引用成员和常量成员变量的初始化:
定义一个类

Class A
{
     public:
          A(int pram1, int pram2, int pram3);
     privite:
          int a;
          int &b;
          const int c; 
}

正确的初始化方式:
A::A(int pram1, int pram2, int pram3):b(pram2),c(pram3)
{
a=pram1;
}
采用初始化列表实现了对常量和引用的初始化。采用括号赋值的方法,括号赋值只能用在变量的初始化而不能用在定义之后的赋值。
凡是有引用类型的成员变量或者常量类型的变量的类,不能有缺省构造函数。默认构造函数没有对引用成员提供默认的初始化机制,也因此造成引用未初始化的编译错误。并且必须使用初始化列表进行初始化const对象、引用对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值