C++学习有哪些要点 C++的要点

2017-08-02 11:39 10 1 收藏

现在的计算机语言有很多种,C,C++,Java,PHP,Python等等,大家对这些语言的难易程度说法不一,其实只要下决心学,就不用管难不难的问题,那么,C++学习有哪些要点呢?

【 tulaoshi.com - C++要点 】

C++学习有哪些要点 C++的要点

要点1:

很多C++程序员还在使用而不是用更新的标准的库。这两者都有什么不同呢?首先,5年前我们就开始反对把.h符号继续用在标准的头文件中。继续使用过时的规则可不是个好的方法。从功能性的角度来讲,包含了一系列模板化的I/O类,相反地只仅仅是支持字符流。另外,输入输出流的C++标准规范接口在一些微妙的细节上都已改进,因此,和在接口和执行上都是不同的。最后,的各组成都是以STL的形式声明的,然而的各组成都是声明成全局型的。

因为这些实质上的不同,你不能在一个程序中混淆使用这两个库。做为一种习惯,在新的代码中一般使用,但如果你处理的是过去编写的代码,为了继承可以用继续用旧保持代码的一致性。

要点2:用引用传递参数时应注意的地方

在用引用传递参数时,最好把引用声明为const类型。这样做的好处是:告诉程序不能修改这个参数。在下面的这个例子中函数f()就是传递的引用:

void f(const int & i);

int main()

{

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

f(2); /* OK */

}

这个程序传递一个参数2给f()。在运行时,C++创建一个值为2的int类型的临时变量,并传递它的引用给f().这个临时变量和它的引用从f()被调用开始被创建并存在直到函数返回。返回时,就被马上删除。注意,如果我们不在引用前加上const限定词,则函数f()可能会更改它参数的值,更可能会使程序产生意想不到的行为。所以,别忘了const。

这个要点也适用于用户定义的对象。你可以给临时对象也加上引用如果是const类型:

struct A{};

void f(const A& a);

int main()

{

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

f(A()); // OK,传递的是一个临时A的const引用

}

要点3:“逗号分离”表达形式

“逗号分离”表达形式是从C继承来的,使用在for-和while-循环中。当然,这条语法规则被认为是不直观的。首先,我们来看看什么是“逗号分离”表达形式。

一个表达式由一个或多个其它表达式构成,由逗号分开,如:

if(++x, --y, cin.good()) //三个表达式

这个if条件包含了三个由逗号分离的表达式。C++会计算每个表达式,但完整的“逗号分离”表达式的结果是最右边表达式的值。因此,仅当cin.good()返回true时,if条件的值才是true。下面是另一个例子:

int j=10;

int i=0;

while( ++i, --j)

{

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

//直到j=0时,循环结束,在循环时,i不断自加

}

要点4,使用全局对象的构造函数在程序启动前调用函数

有一些应用程序需要在主程序启动前调用其它函数。如:转态过程函数、登记功能函数都是必须在实际程序运行前被调用的。最简单的办法是通过一个全局对象的构造函数来调用这些函数。因为全局对象都是在主程序开始前被构造,这些函数都将会在main()之前返回结果。如:

class Logger

{

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

public:

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

Logger()

{

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

activate_log();//译者注:在构造函数中调用你需要先运行的函数

}

};

Logger log; //一个全局实例

int main()

{

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

record * prec=read_log();//译者注:读取log文件数据

//.. 程序代码

}

全局对象log在main()运行之前被构造,log调用了函数activate_log()。从而,当main()开始执行时,它就可以从log文件中读取数据。

毫无疑问地,在C++编程中内存管理是最复杂和最容易出现bug的地方。直接访问原始内存、动态分配存储和最大限度的发挥C++指令效率,都使你必须尽力避免有关内存的bug。

要点5:避免使用复杂构造的指向函数的指针

指向函数的指针是C++中可读性最差的语法之一。你能告诉我下面语句的意思吗?

void (*p[10]) (void (*)());

P是一个“由10个指针构成的指向一个返回void类型且指向另一个无返回和无运算的函数的数组”。这个麻烦的语法真是让人难以辨认,不是吗?你其实可以简单的通过typedef来声明相当于上面语句的函数。首先,使用typedef声明“指向一个无返回和无运算的函数的指针”:

typedef void (*pfv)();

接着,声明“另一个指向无返回且使用pfv的函数指针”:

typedef void (*pf_taking_pfv) (pfv);

现在,声明一个由10个上面这样的指针构成的数组:

pf_taking_pfv p[10];

与void (*p[10]) (void (*)())达到同样效果。但这样是不是更具有可读性了!

C++学习有哪些要点 C++的要点

要点6:指向成员的指针

一个类有两种基本的成员:函数成员和数据成员。同样的,指向成员的指针也有两种:指向函数成员的指针和指向数据成员的指针。后则其实并不常用,因为类一般是不含有公共数据成员的,仅当用在继承用C写的代码时协调结构(struct)和类(class)时才会用到。

指向成员的指针是C++语法中最难以理解的构造之一,但是这也是一个C++最强大的特性。它可以让你调用一个类的函数成员而不必知道这个函数的名字。这一个非常敏捷的调用工具。同样的,你也可以通过使用指向数据成员的指针来检查并改变这个数据而不必知道它的成员名字。

指向数据成员的指针

尽管刚开始时,指向成员的指针的语法会使你有一点点的迷惑,但你不久会发现它其实同普通的指针差不多,只不过是*号的前面多了::符号和类的名字,例:

定义一个指向int型的指针:

int * pi;

定义一个指向为int型的类的数据成员:

int A::*pmi; //pmi是指向类A的一个int型的成员

你可以这样初始化它:

class A

{

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

public:

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

int num;

int x;

};

int A::*pmi = & A::num;

上面的代码是声明一个指向类A的一个int型的num成员并将它初始化为这个num成员的地址.通过在pmi前面加上*你就可以使用和更改类A的num成员的值:

A a1, a2;

int n=a1.*pmi; //把a1.num赋值给n

a1.*pmi=5; // 把5赋值给a1.num

a2.*pmi=6; // 把6赋值给6a2.num

如果你定义了一个指向类A的指针,那么上面的操作你必须用 ->*操作符代

替:

A * pa=new A;

int n=pa->*pmi;

pa->*pmi=5;

指向函数成员的指针

它由函数成员所返回的数据类型构成,类名后跟上::符号、指针名和函数的参数列表。举个例子:一个指向类A的函数成员(该函数返回int类型)的指针:

class A

{

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

public:

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

int func ();

};

int (A::*pmf) ();

上面的定义也就是说pmf是一个指向类A的函数成员func()的指针.实际上,这个指针和一个普通的指向函数的指针没什么不同,只是它包含了类的名字和::符号。你可以在在任何使用*pmf的地方调用这个函数

func():

pmf=&A::func;

A a;

(a.*pmf)(); //调用a.func()

如果你先定义了一个指向对象的指针,那么上面的操作要用->*代替:

A *pa=&a;

(pa->*pmf)(); //调用pa->func()

指向函数成员的指针要考虑多态性。所以,当你通过指针调用一个虚函数成员时,这个调用将会被动态回收。另一个需要注意的地方,你不能取一个类的构造函数和析构函数的地址。

要点7、避免产生内存碎片

经常会有这样的情况:你的应用程序每运行一次时就因为程序自身缺陷而产生内存漏洞而泄漏内存,而你又在周期性地重复着你的程序,结果可想而知,它也会使系统崩溃。但怎样做才能预防呢?

首先,尽量少使用动态内存。在大多数情况下,你可能使用静态或自动存储或者是STL容器。第二,尽量分配大块的内存而不是一次只分配少量内存。举个例子:一次分配一个数组实例所需的内存,而不是一次只分配一个数组元素的内存。

要点8、是delete还是delete[]

在程序员中有个荒诞的说法:使用delete来代替delete[]删除数组类型时是可以的!

举个例子吧:

int *p=new int[10];

delete p; //错误,应该是:delete[] p

上面的程序是完全错误的。事实上,在一个平台上使用delete代替delete[]的应用程序也许不会造成系统崩溃,但那纯粹是运气。你不能保证你的应用程序是不是会在另一个编译器上编译,在另一个平台上运行,所以还是请使用delete[]。

要点9、优化成员的排列

一个类的大小可以被下面的方式改变:

struct A

{

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

bool a;

int b;

bool c;

}; //sizeof (A) == 12

在我的电脑上sizeof (A) 等于12。这个结果可能会让你吃惊,因为A的成员总数是6个字节:1+4+1个字节。那另6字节是哪儿来的?编译器在每个bool成员后面都插入了3个填充字节以保证每个成员都是按4字节排列,以便分界。你可以减少A的大小,通过以下方式:

struct B

{

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

bool a;

bool c;

int b;

}; // sizeof (B) == 8

这一次,编译器只在成员c后插入了2个字节。因为b占了4个字节,所以就很自然地把它当作一个字的形式排列,而a和c的大小1+1=2,再加上2个字节就刚好按两个字的形式排列B。

要点10、为什么继承一个没有虚析构函数的类是危险的?

一个没有虚析构函数的类意味着不能做为一个基类。如std::string,std::complex, 和 std::vector 都是这样的。为什么继承一个没有虚析构函数的类是危险的?当你公有继承创建一个从基类继承的相关类时,指向新类对象中的指针和引用实际上都指向了起源的对象。因为析构函数不是虚函数,所以当你delete一个这样的类时,C++就不会调用析构函数链。举个例子说明:

class A

{

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

public:

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

~A() // 不是虚函数

{

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

// ...

}

};

class B: public A //错; A没有虚析构函数

{

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

public:

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

~B()

{

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

// ...

}

};

int main()

{

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

A * p = new B; //看上去是对的

delete p; //错,B的析构函没有被调用

}

要点11、以友元类声明嵌套的类

当你以友元类声明一个嵌套的类时,把友元声明放在嵌套类声明的后面,而不前面。

class A

{

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

private:

int i;

public:

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

class B //嵌套类声明在前

{

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

public:

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

B(A & a) { a.i=0;};

};

friend class B;//友元类声明

};

如果你把友元类声明放在声明嵌套类的前面,编译器将抛弃友元类后的其它声明

相关阅读:C++多继承

来源:https://www.tulaoshi.com/n/20170802/2662967.html

延伸阅读
    富有活力的语言需要不断改变和成长,C++也不例外。在本文中,Bjarne Stroustrup提出了自己对C++的设计和演化的看法。 !-- frame contents -- !-- /frame contents -- 为了让编译器、工具和类库实现者跟上节奏,让用户吸收标准C++所支持的编程技术,在早有预计的、沉寂了几年之后,委员会再次考虑...
Stephan Lavavej提出了一个非常有趣也很尖锐的问题:“C++的未来在哪里?” 这个问题是有解的。没有哪个语言会成为永恒,不是吗?(尽管C语言现在依旧生气勃勃)我不希望C++在2017年,或者甚至在2057年也依然那么有活力。在计算机行业,50年已经是一个几乎不可思议的时间了;虽然到今年为止,晶体管已有60年的历史。所以,在我问“C++的未来在哪...
    作者:伊利贵 张虹 2001年01月05日 14:48 现在,对于一个正在进行项目开发的公司来说,选择一门Windows下的开发语言已经不再像以前那么容易。C++曾经是商业开发最好的选择,但是现在,开发者们已经没有时间,也没有耐心一遍遍重复“编写代码——编译——排错”这样一个无休止的循环,也不再想去一次次地修补多年前编制...
记得刚学C++的时候,喜欢研究API,当时同事有一个高手,写了段代码,我在写程序的时候,莫明妙的,机器突然关掉了!我正在纳闷的时候,我听到了他的奸笑! 原来是他干的,后来我研究了好久InitiateSystemShutdown这个API函数,了解被作弄的原理了,因为我的机器加入了Windows的域,而且域的超级用户我也设置成对我本机有Administrato...
1.把C++当成一门新的语言学习(和C没啥关系!真的。 !-- frame contents -- !-- /frame contents -- ); 2.看《Thinking In C++》,不要看《C++变成死相》; 3.看《The C++ Programming Language》和《Inside The C++ Object Model》,不要因为他们很难而我们自己是初学者所以就不看; 4.不要被VC、BCB、BC、M...

经验教程

698

收藏

7
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部