const常量
- 使用该修饰符定义常量,必须初始化
- 一旦定义任何地方没法改
- 如果定义的是一个整型常量,关键字 int 可以省略
const常量可以与指针一起使用,有 3 组合情况:
-
指向常量的指针:是指一个指向常量的指针变量
const char*p =“abcd”;,所以不能改变指针指向的字符,比如 p【3】=‘h’ 是错误的,因为它指向的事一个字符串常量,所以不能更改内容,但可以改变该指针的所指方向:如 p=“kkvkvk”;那就是对的; -
常指针:是一个指向固定的一个指针;
char const *p=“45678”; 若这样子操作则是错的:p=“kkvkvk”;若是 p[3]='k’则对的,因为指向的地址没变; -
指向常量的常指针:const char const*p=“46df”;这个就怎么不能改了;
int const* a 相当于 const int *a 这是指向常量的指针
(可改变指针指向地址,不能改变指针指向的变量的内容)
不是 int *const a; 这是常指针;(不可以改变指针指向的变量,但可以改变该变量的内容)
#include<iostream>
using namespace std;
int main()
{
const int a1=7;
int const a2=8;
int c1=9;
int c2=10;
const int *d1=&a1;
const int *d2=&c1;
int const *e1=&a1;
int const *e2=&c1;
e2=e1;
//*e2=33;
int *const f1=&c1;
int *const f2=&c2;
// int *const f3=&a1;
// f2=f1;
*f2=33;
const int *const g1=&a2;
const int *const g2=&c2;
//g2=g1;
cout<<"a1="<<a1<<"a2="<<a2<<endl;
cout<<"d1="<<d1<<"d2="<<d2<<endl;
cout<<"e1="<<e1<<"e2="<<e2<<endl;
cout<<"f1="<<f1<<"f2="<<f2<<endl;
cout<<"g1="<<g1<<"g2="<<g2<<endl;
return 0;
const常量初始化
如 const int a;a的值不能修改,不能给它赋值,如何才能让它一开始就拥有一个值?
1、在声明的时候对他进行初始化
const int a=1;
2、在函数中声明的形参,在函数被调用时会得到实参的值。
3、在类中只能通过初始化列表初始化
详细看这里
静态变量
- 跨文件,隐藏
当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。 - static的第二个作用是保持变量内容的持久
存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。共有两种变量存储在静态存储区:全局变量和static变量,只不过和全局变量比起来,static可以控制变量的可见范围,说到底static还是用来隐藏的。虽然这种用法不常见,但我还是举一个例子 - static的第三个作用是默认初始化为0.其实全局变量也具备这一属性
- 静态成员可以直接用类名调用
内联函数在编译的时候是将该函数的目标代码插入到每个调用该函数的地方
- 不能有递归
- 不能有静态数据成员
- 不能有循环
- 不能有switch和goto语句;
- 不能包含数组
若内联函数没有满足上述要求将会被作为普通函数处理
#include<iostream>
using namespace std;
inline int locate();/先声明了一个内敛函数
int main()
{
locate();
}
inline int locate()
{
cout<<"hh"<<endl;
}
多态性
面向对象有两种编译方式:静态联编和动态联编;
1.静态联编是指系统在编译时就决定如何实现某一动作,速度快;
2.动态联编是系统在运行的时候动态决定某一动作,灵活度高;
编译时多态性是通过使用重载来获得,运行时多态性通过视同继承和虚函数获得的;
实现多态性的机制叫做动态绑定
友元类与继承
- 友元关系不能继承。基类的友元对派生类的成员没有特殊访问 权限。如果基类被授予友元关系,则只有基类具有特殊访问权限,该基类的派生类不能访问授予友元关系的类
例:
#include <iostream>
using namespace std;
class B;
class A
{
int a;
public:
A(int x=0) { a=x; }
friend class B;
};
class B
{
int b;
public:
void fun(A& ob){ cout << ob.a << endl;}
};
class C:public B
{
public:
//void fun2(A& ob){ cout <<ob.a <<endl;} //派生类新加的函数却不能访问A,此句会报错
};
void main()
{
A a(55);
C c;
c.fun(a); //C是B的派生类 通过基类B的函数fun仍然可以访问
}
多重继承中的命名冲突
当两个或多个基类中有同名的成员时,如果直接访问该成员,就会产生命名冲突,编译器不知道使用哪个基类的成员。这个时候需要在成员名字前面加上类名和域解析符::,以显式地指明到底使用哪个类的成员,消除二义性。
#include<iostream>
using namespace std;
class base { public: int x; };
class One:public base{};
class Two:public base{};
class OT:public One,public Two{
public: int func();
};
void main() { OT p; p.One::x = 0; }//或p.Two::x = 0; 而 p.base::x = 0; 是错误的
派生类只能访问基类的成员,不可以放访问基类的基类成员
注意点:静态的运用
#include<iostream>
using namespace std;
class Obj{
static int i;
public:
Obj(){i++;}
~Obj(){i--;}
static int getVal(){return i;}
};
int Obj::i=0;
void f (){Obj ob2;cout<<ob2.getVal();}
int main(){
Obj obl;
f();
Obj*ob3=new Obj;//这一步很特殊
cout<<ob3->getVal();
delete ob3;
cout<<Obj::getVal();
return 0;//结果为221
}
话说指针ob3他确确实实有调用构造函数,所以count是有加到3的,关键是为什么输出的是 2呢
因为 f()函数里面的生成对象ob2 是个局部变量,函数执行完毕,自动释放空间,自然就要析构掉这个对象