辅修C++要期末考了
看PPT,总结了一些东西,不全不一定对
1.cout<<’\101’;字符’A’的ASCII码,与’A’等价
2.C++常用转义字符
3.指针的类型转换
void 指针变量能够存放任意内存地址。因为没有关联类型,编译器无法解释所指对象,程序中必须对其作强制类型转换,才可以按指定类型数据使用
#include<iostream>
using namespace std ;
int main()
{ int a = 65 ;
int * ip ;
void * vp = &a ;//定义无类型指针以整变量地址初始化
cout << * ( int * ) vp << endl ;//强类型转换后访问对象
cout << * ( char * ) vp << endl ;//转换成字符型指针
ip = ( int * ) vp ;//向整型指针赋值
cout << ( * ip ) << endl ;
}
4.常量const
程序中以只读形式访问标识常量
定义形式: const 类型 常量标识符 = 常量值 ;
指向常量的指针:
const 类型 * 指针
或 类型 const * 指针
指针常量:
类型 * const 指针
注:指针常量的值只能在定义的时候初始化
int max ;
int * const pmax = & max , * p ;//定义时初始化指针pmax
* pmax = 1000 ;
cout << "max1 = " << * pmax << endl ;
p = new int ;
* p = 2000 ;
cout << " * p = " << * p << endl ;
// pmax = p ; // 错误
p = pmax ;
指向常量的指针常量:
const 类型 * const 指针
const 类型 * const 指针
const 类型 & 引用名 = 对象名 ;
例如:
int a=314;
const int & ra=a; //ra是a的常引用
//ra=618; //错误,不能通过常引用对对象a执行写操作
a=618; //正确
|
5.运算符优先级
6.赋值表达式称为左值表达式,允许关联赋值
x = y = z + 2 ;//等价于x = y = ( z + 2 ) ;
7.常用的输出格式控制符
|
注:包含头文件 iomanip
8.类外用 “ . ” 和 “ -> ” 运算符访问对象成员
9.有关构造函数:
用初始式对数据成员置值(特别的,可以初始化父类),常量值在最右
Date:: Date(int y, int m, int d) : year(y), month(m), day(d)
{ cout<<year<<"/"<<month<<"/"<<day<<": Date object initialized."<<"\n" ;
}
首先调用成员类构造函数,再初始化自身数据成员
常量赋值:
class A
{ const int size=0;}这样写是错误的。
正确写法1:
class A
{ A(){ const int size=0;}}
正确写法2:
class A
{ static const int size=0;}
非静态常量是不能在类中初始化的,可以声明,只有静态整形常量可以在类中直接初始化。你像你的正确写法2,如果换成是class A{static const string m=“123”;}也是错误的。而且常量只有初始化操作,而无赋值操作。
const常量具有从“构造函数初始化到析构函数执行”之间的不可变性,所以需要在构造函数中初始化
10.复制构造函数
复制构造函数用一个已有同类对象的数据对正在建立的对象进行数据初始化
语法形式
类名 :: 类名(const 类名 & 引用名 , …);
(1)用已有对象初始化新创建对象
(2)函数的类类型实参初始化形参时,要调用复制构造函数
(3)函数返回类类型时,通过复制构造函数建立临时对象
11.复制构造函数与赋值函数
构造函数、析构函数、赋值函数是每个类最基本的的函数。每个类只有一个析构函数和一个赋值函数。但是有很多构造函数(一个为复制构造函数,其他为普通构造函数。对于一个类A,如果不编写上述四个函数,c++编译器将自动为A产生四个默认的函数,即:
- A(void) //默认无参数构造函数
- A(const A &a) //默认复制构造函数
- ~A(void); //默认的析构函数
- A & operator = (const A &a); //默认的赋值函数
既然能自动生成函数,为什么还需要自定义?原因之一是“默认的复制构造函数”和"默认的赋值函数“均采用”位拷贝“而非”值拷贝“
位拷贝 v.s. 值拷贝
位拷贝拷贝的是地址,而值拷贝拷贝的是内容。
如果定义两个String对象a, b。当利用位拷贝时,a=b,其中的a.val=b.val;但是a.m_data=b.m_data就错了:a.m_data和b.m_data指向同一个区域。这样出现问题:
a.m_data原来的内存区域未释放,造成内存泄露
a.m_data和b.m_data指向同一块区域,任何一方改变,会影响到另一方
当对象释放时,b.m_data会释放掉两次
因此
当类中还有指针变量时,复制构造函数和赋值函数就隐含了错误。此时需要自己定义。
12.常成员
常数据成员是指数据成员在实例化被初始化后约束为只读。
常成员函数是指成员函数的this指针被约束为指向常量的常指针,函数体内不能修改数据成员的值。
13.静态成员
类成员冠以static声明时,称为静态成员。
静态数据成员为同类对象共享。
静态成员函数与静态数据成员协同操作。
静态成员函数没有this指针,只能对静态数据操作
在类外调用静态成员函数用 “类名 :: ”作限定词,或通过对象调用
声明与定义静态数据成员:
class counter
{ static int num ;
} ;
int counter :: num = 0 ;
14.重载运算符
不能重载的算符
. :: . ?: sizeof*
格式:
类型 类名 :: operator op ( 参数表 )
{
// 相对于该类定义的操作
}
友元重载运算符:
在第一个参数需要隐式转换的情形下,使用友元函数重载
运算符是正确的选择
友元函数没有 this 指针,所需操作数都必须在参数表显式
声明,很容易实现类型的隐式转换
C++中不能用友元函数重载的运算符有
= () [] ->
friend Complex operator- ( const Complex & c1, const Complex & c2 ) ;
....
Complex operator - ( const Complex & c1, const Complex & c2 )
{ double r = c1.Real - c2.Real ; double i = c1.Image - c2.Image ;
return Complex ( r, i ) ;
}
若一运算符的操作需要修改类对象状态时,应该用成员函数重载;
需要左值操作数的运算符(如 ++,–),若重载为友元函数时要用引用参数
如果运算符的操作数(尤其是第一个操作数)希望有隐式转换,则
必须用友元函数重载
运算符 ++和 - - 有两种方式:
前置方式: ++Aobject --Aobject
一元 成员函数 重载 A :: A operator++ () ;
解释为: Aobject . operator ++( ) ;
友元函数 重载 friend A operator++ (A &) ;
解释为: operator ++( Aobject ) ;
后置方式: Aobject ++ Aobject –
二元 成员函数 重载 A :: A operator++ (int) ;
解释为: Aobject . operator ++( 0 ) ;
友元函数 重载: friend A operator++ (A &, int) ;
解释为: operator++(Aobject, 0)
重载赋值运算符:
operator= 必须重载为成员函数
重载函数原型为:
类型 & 类名 :: operator= ( const 类名 & ) ;
重载下标运算符 []:
重载格式 类型 类 :: operator[] ( 类型 ) ;
int & operator [ ] ( int i ) { return v [ i ] ; }