《C++ Primer》学习之基础知识及所用该注意的问题

来源:互联网 发布:安卓手机怎么重置网络 编辑:程序博客网 时间:2024/05/16 23:54

多维数组:多维数组最简单的理解是数组的数组,严格的说在C++中没有多维数组。时刻把多维数组当成数组的数组来对使用的时候理解起来会比较轻松许多。

下面来讲讲多维数组跟指针结合使用的问题,这个问题很头痛,一直都用不好。先来理解下面几个定义

int ia[3][4];//array of size 3,each element is an array of ints of size 4

int (*ip)[4] = ia;//ip points to an array of 4 ints

ip = &ia[4];//ia[2] is an array of 4 ints

由多维数组转换成指针类型应该是指向第一个内层数组的指针。定义指向数组的指针与定义数组类似,首先声明元素类型,后接数组名字和维数。

int *ip[4];//array of pointers to int

int (*ip)[4];//pointer to an array of 4 ints


bitset使用:bitset<30> bitset_quiz;//定义一个bitset类对象,含有30位,每一位初始化为0;

bitset_quiz.set(27);//27位设置为1

bitset_quiz.reset(27);//27位恢复为0

bitset在有些时候是个很有用的工具,记得用哦


sizeof:返回对象或类型的大小,单位是字节。需注意下面几点

1.对char类型或值为char类型的表达式做此操作保证得1

2.对引用类型做sizeof操作将返回存放此引用类型对象所需的内存空间大小

3.对指针做sizeof操作将返回存放指针所需内存大小;注意,如果要获取该指针所指向对象的大小,则必须对该指针进行解引用

4.对数组做sizeof操作等效于九昂对其元素类型做sizeof操作的结果乘上数组元素的个数,可以通过此方法求出数组的长度


goto语句是函数内部无条件跳转,实现从goto语句跳转到同一函数内某个带标号的语句

函数返回值为引用时:

const string &shorterString(const string &s1,const string &s2)

{

return s1.size() < s2.size()?s1:s2

}

这里需要注意的是返回值是引用的话,要保证被返回的值也是引用,因为不能返回局部变量的引用。指针也是这样的


函数指针:函数指针定义

#include<stdio.h>
intmax(intx,inty){return(x>y?x:y);}
intmain()
{
int(*ptr)(int,int);
inta,b,c;
ptr=max;
scanf("%d%d",&a,&b);
c=(*ptr)(a,b);
printf("a=%d,b=%d,max=%d",a,b,c);
}

或者,这两段代码来自百度百科

1.定义函数指针类型:
typedef int (*fun_ptr)(int,int);
2.声明变量,赋值:
fun_ptr max_func=max;
也就是说,赋给函数指针的函数应该和函数指针所指的函数原型是一致的。
例二、
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<stdio.h>
voidFileFunc()
{
printf("FileFunc\n");
}
voidEditFunc()
{
printf("EditFunc\n");
}
voidmain()
{
typedefvoid(*funcp)();
funcppfun=FileFunc;
pfun();
pfun=EditFunc;
pfun();
}

类中构造函数:类的构造函数初始化的时候,可以使用初始化列表,也可以在构造函数定义中进行赋值操作。初始化列表用法:

Sales::Sales():isbn(0),units_sold(0){};在构造函数定义中进行复制用法:Sales::Sales(){isbn = 0; units_sold = 0};这两种方法在大部分情况是相同的效果和性能,但要注意他们的原理是不一样的,初始化列表是初始化操作,在定义中进行赋值是赋值操作。要当心有些时候是不能进行赋值操作的。比如没有默认构造函数的类类型的成员,以及const或引用类型的成员,不管是哪种类型都必须在构造函数初始化列表中进行初始化。

还应该注意的是构造函数初始化列表中,初始化顺序的问题。初始化顺序不是初始化列表中的书写顺序,而是类中成员的定义顺序。这点很重要,忽视这点的话,会引起比较让人郁闷的错误。比如

class X{

int i;

int j;

public:

X(int val):j(val),i(j){}

};

用j去初始化i的时候会出错,因为i在类中定义在j前面,所以需要先对i进行初始化。

初始化式可以是任意表达式

Sales_item(const std::string &book,int cnt,double price):isbn(book),units_sold(cnt),revenue(cnt * price){}

类中的Static成员函数和成员变量:无论是成员变量还是成员函数,前面用static修饰之后,就是一个共享的函数和变量。其只跟定义此变量的类相关,跟此类的变量是相对独立的。换句话说其不属于任何类的对象,没有this指针。但可以通过类的对象进行调用,或者作用域操作符进行应用::。也可以理解static成员函数可以直接访问所属类的static成员,但不能直接访问非static成员。原因我是这样理解,非static成员或函数在定义类对象之前都只是定义,没有实际的内存和初始化值,是不可用的状态。而static在定义的时候就已经分配了内存,其已经处于可用状态,实际的函数中去使用不可用的成员和函数时是不被允许的。static成员比全局成员好的地方就是,这个static的作用域被限定在定义的类中,不像全局变量,随处都可用。这样实现一些灵活性。

注意:像使用任意的类成员一样,在类定义体之外使用的时候,必须指定此成员是在哪个类中定义的。然而,static关键字只能用于类定义体内部的声明中,定义不能表示为static。一般而言,类的static成员跟其他成员一样,不能在类定义体中初始化。相反static数据成员通常是在定义时才初始化。但const static类型是个例外。其可以在声明的时候进行初始化。


基类和派生类中的非虚函数和虚函数:

虚函数很明确,在声明的时候加上virtual关键字的函数。虚函数只能在声明的时候表示,不能在定义的时候。虚函数往往是基类中希望派生类进行定义的函数。

虚函数进行使用的时候根据参数,定义格式进行自动的选取派生类和基类中的定义形式。这也是跟非虚函数的区别。如果是非虚函数,在派生类中定义了一个跟基类中重名的函数,在派生类中或基类中只能选择所定义类中的同名函数,不能智能选取。这时另外一个问题就需要注意了,刚刚所说的情况并不表示,在派生类中不能使用基类中的同名函数,只有在派生类中没有定义同名函数的时候,可以使用基类中的同名函数。成员变量也是这种情况。

函数调用遵循一下四个步骤:

1.首先确定进行函数调用的对象,引用或指针的静态类型

2.在该类中查找函数,如果找不到,就在直接基类中查找,如此循着类的继承链往上找,直到找到该函数或者查找完最后一个类。如果不能在类或其相关基类中找到该名字,则调用是错误的

3.一旦找到了改名字,就进行常规类型检查,查看如果给定找到的定义,该函数调用是否合法

4.假定函数调用合法,编译器就生成代码。如果函数是虚函数且通过引用或指针调用,则编译器生成代码以确定根据对象的动态类型运行哪个函数版本,否则编译器生成代码直接调用函数。

还有一个概念纯虚函数,其定义形式是在函数形参表后面写上=0以指定纯虚函数。纯虚函数说明,该函数的后代类型提供可以覆盖的接口,但是这个类中的版本绝不会调用。更重要 的是用户将不能创建该类类型的对象。

含有(或继承)一个或多个纯虚函数的类是抽象基类。除了作为抽象基类的派生类的对象的组成部分,不能创建抽象类型的对象。


0 0
原创粉丝点击