参考: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=="<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 构造函数"<
友元类:可参考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对象、引用对象。