天天看点

努力学习c++的一天(九)

参考:http://c.biancheng.net/cpp/biancheng/view/2971.html

参考:https://ruochen.blog.csdn.net/article/details/90719951?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.control

1. 构造函数怎么写

首先,当类被实例化后,会自动调用构造函数,由构造函数完成对象的初始化工作,构造函数的作用:初始化对象的数据成员;

因此,构造函数中的内容:初始化对象成员(包括public、private);

class Student{

private:

char *m_name;

int m_age;

float m_score;

public:

//声明构造函数

Student(char *name, int age, float score);

//声明普通成员函数

void show();

};

//定义构造函数

Student::Student(char *name, int age, float score){

m_name = name;

m_age = age;

m_score = score;

}

//采用参数初始化表,成员变量的赋值顺序由它们在类中的声明顺序决定,初始化 const 成员变量的唯一方法就是使用参数初始化表。

Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){

//TODO:

}

在栈上创建对象时,实参位于对象名后面,例如

Student stu("小明", 15, 92.5f)

;在堆上创建对象时,实参位于类名后面,例如

new Student("李华", 16, 96),

调用没有参数的构造函数也可以省略括号。

构造函数必须是 public 属性的,否则创建对象时无法调用。

  • 不管是声明还是定义,函数名前面都不能出现返回值类型,即使是 void 也不允许;
  • 函数体中不能有 return 语句。

构造函数是允许重载的。一个类可以有多个重载的构造函数,创建对象时根据传递的实参来判断调用哪一个构造函数。

2. 命名空间怎么写

为了解决合作开发时的命名冲突问题,C++ 引入了命名空间(Namespace)

namespace name{

    //variables, functions, classes

}

使用变量、函数时要指明它们所在的命名空间。

Li :: fp = fopen("one.txt", "r"); //使用小李定义的变量 fp

Han :: fp = fopen("two.txt", "rb+"); //使用小韩定义的变量 fp

不建议全局使用 using namepace ×,可能会引起问题:增加了命名冲突的风险,但是可以局部使用,例如:在 main() 函数中声明命名空间 std,它的作用范围就位于 main() 函数内部,如果在其他函数中又用到了 std,就需要重新声明

#include <iostream>

void func(){
    //必须重新声明
    using namespace std;
    cout<<"http://c.biancheng.net"<<endl;
}

int main(){
    //声明命名空间std
    using namespace std;
   
    cout<<"C语言中文网"<<endl;
    func();

    return 0;
}      

不同的.h中可以使用相同名字的namespace吗?  可以,会自动合并为一个名字空间,可以理解为追加

3. 常用的头文件

  • #include<iostream>    使用输入输出时
  • #include <string>     //字符串类

4. 内存分配

在C语言中,动态分配内存用 malloc() 函数,释放内存用 free() 函数;C++中使用new 和 delete:new 用来动态分配内存,delete 用来释放内存。

int *p = new int;  //分配1个int型的内存空间
delete p;  //释放内存      
int *p = new int[10];  //分配10个int型的内存空间
delete[] p;      

通常 new 和 delete、new[] 和 delete[] 操作符应该成对出现

5. 为什么会有内联函数?

函数调用是有时间和空间开销的。如果函数体代码比较多,需要较长的执行时间,那么函数调用机制占用的时间可以忽略;如果函数只有一两条语句,那么大部分的时间都会花费在函数调用机制上,这种时间开销就就不容忽视。

指定内联函数的方法很简单,只需要在函数定义处增加 inline 关键字。一般只将那些短小的、频繁调用的函数声明为内联函数。在类体中定义的成员函数会自动成为内联函数,在类体外定义的不会。

  • //内联函数,交换两个数的值
  • inline void swap(int *a, int *b){
  •     int temp;
  •     temp = *a;
  •     *a = *b;
  •     *b = temp;
  • }

6. 创建类和对象

c++一般在 .h文件中创建类,因为类只是一个模板(Template),编译后不占用内存空间,所以在定义类时不能对成员变量进行初始化,因为没有地方存储数据。只有在创建对象以后才会给成员变量分配内存,这个时候就可以赋值了。

通常将类的声明放在头文件中,而将成员函数的定义放在源文件中。

两种创建对象的方式:一种是在栈上创建,

Student stu;

Student *pStu = &stu;

另外一种是在堆上创建,

Student *pStu = new Student;

delete pStu; //删除对象      

栈内存是程序自动管理的,不能使用 delete 删除在栈上创建的对象;堆内存由程序员管理,对象使用完毕后可以通过 delete 删除。

7. 访问权限

在类的内部(定义类的代码内部,定义类的.h和.cpp),无论成员被声明为 public、protected 还是 private,都是可以互相访问的,没有访问权限的限制。

在类的外部(定义类的代码之外),只能通过对象访问成员,并且通过对象只能访问 public 属性的成员,不能访问 private、protected 属性的成员。

成员变量大都以

m_

开头,这是约定成俗的写法,不是语法规定的内容。以

m_

开头既可以一眼看出这是成员变量,又可以和成员函数中的形参名字区分开。

//类的声明

class Student{

private: //私有的

   char *m_name;

   int m_age;

   float m_score;

public: //共有的

   void setname(char *name);

   void setage(int age);

   void setscore(float score);

   void show();

};

根据C++软件设计规范,实际项目开发中的成员变量以及只在类内部使用的成员函数(只被成员函数调用的成员函数)都建议声明为 private,而只将允许通过对象调用的成员函数声明为 public。

给成员变量赋值的函数通常称为 set 函数,它们的名字通常以

set

开头,后跟成员变量的名字;读取成员变量的值的函数通常称为 get 函数,它们的名字通常以

get

开头,后跟成员变量的名字。

除了 set 函数和 get 函数,在创建对象时还可以调用构造函数来初始化各个成员变量

8. 析构函数

析构函数没有参数,不能被重载,因此一个类只能有一个析构函数。

在所有函数之外创建的对象是全局对象,它和全局变量类似,位于内存分区中的全局数据区,程序在结束执行时会调用这些对象的析构函数。

在函数内部创建的对象是局部对象,它和局部变量类似,位于栈区,在局部函数执行结束时会调用这些对象的析构函数。

new 创建的对象位于堆区,通过 delete 删除时才会调用析构函数;如果没有 delete,析构函数就不会被执行。

9. this指针

this 是 const 指针,this 只能在成员函数内部使用,用在其他地方没有意义,也是非法的

10. 静态成员变量和静态成员函数

使用静态成员变量来实现多个对象共享数据的目标,就相当于类中的全局变量;

static 成员变量必须在类声明的外部初始化,具体形式为:

type class::name = value;

static 成员变量既可以通过对象来访问,也可以通过类来访问

静态成员函数只能访问静态成员,静态成员函数与普通成员函数的根本区别在于:普通成员函数有 this 指针,可以访问类中的任意成员;而静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。

11. const关键字

const 可以用来修饰成员变量、成员函数以及对象。如果你不希望某些数据被修改,可以使用

const

关键字加以限定。

const 成员函数可以使用类中的所有成员变量,但是不能修改它们的值;常成员函数需要在声明和定义的时候在函数头部的结尾加上 const 关键字

class Student{      

public:

Student(char *name, int age, float score);

void show();

//声明常成员函数

char *getname() const;

int getage() const;

float getscore() const;

private:

char *m_name;

int m_age;

float m_score;

};

//定义常成员函数

char * Student::getname() const{

return m_name;

}

12. friend友元函数和友元类

在当前类以外定义的、不属于当前类的函数也可以在类中声明,但要在前面加 friend 关键字,这样就构成了友元函数。

友元函数不同于类的成员函数,在友元函数中不能直接访问类的成员,必须要借助对象。

class Student{

public:

Student(char *name, int age, float score);

public:

friend void show(Student *pstu); //将show()声明为友元函数

private:

char *m_name;

int m_age;

float m_score;

};

//非成员函数

void show(Student *pstu){

cout<<pstu->m_name<<"的年龄是 "<<pstu->m_age<<",成绩是 "<<pstu->m_score<<endl;

}