c到c++

从C过渡到C++

Authur:SYK

Date:2023-3-2

introduction:本文==适合已经有c语言经验的读者,主要目的是快速上手c++。至于c++面向对象的部分本文只做简要概述。想要深入的读者可以自行查阅有关知识点的资料==。有错误可以指出来。

参考文献:

C++ 教程 | 菜鸟教程 (runoob.com)

(10条消息) 如何从C快速过渡到C++_迷亭1213的博客-CSDN博客

1.标准库

C标准库的头文件xx.h基本上变成了cxx

例如 ===> < cstdio>

2.输入输出流和命名空间

输出:cout <<

c中 printf("hello");
c++中  cout<< "hello"

输入:cin >>

c中 
int x;
scanf("%d",&x);
c++中  
cin>> x;

使用命名空间 using namespace std(命名空间的名字)

为什么开始学c++的时候,都要以

#include

using namespace std;

为开头。

因为在调用 cin cout 的时候,实际上是调用 std:cin std:cout.这里因为使用了命名空间,所以就省略了。

endl 换行符

cout << endl

3.引用变量

定义引用变量时必须指明其引用的是哪个变量,且不能再指向其他变量

int a = 3;
int &r = a;

&r就代表a的地址。r++相当于a++;

4.引用形参

#include  
using namespace std;

void swap(int &x, int &y) //X就是a,y就是b,没有产生新的内存块
{
	int t = x;
	x = y;
	y = t;
}

int main() 
{
	int a = 3, b = 4;
	cout << a << '\t' << b << endl;
	swap(a, b);
	cout << a << '\t' << b << endl;
}

5.默认形参,函数重载

默认形参

int find(a=1){
	return a
}

类似于javapython当调用这个函数没有传参的时候,就会调用默认值。

函数重载

int find(int a){
	return a+1;
}
int find(int a,int b){
	return a+b;
}

当函数名相同的时候,传参不同或者返回类型不同都会造成函数的重载。

6.函数模板

模板参数==可以自动推断类型,为避免歧义,建议使用时还是加上<类型>==

别称:泛型

template //每一个函数模板都需要加这个
T add(T x, T y)
{
	return x + y;
}

#include 
#include 

using namespace std;

template
T add(T x, T y)
{
    return x + y;
}

int main()
{
    区别:------
    cout << add(5, 3) << endl; //自动推断类型
    cout << add(5, 7.8) << endl; //歧义性
    cout << add("hello", " world") << endl;
}

7.String和Vector

String

string s = "hello", s2 = "world"

常用方法:

int a=s.size() //取大小
s=s.substr(1,3) //取第1~3位的字符,返回字符串
int a=s.find("orl") //查找字符串,返回所在下标
s.insert(3,"ABCD") //在下标3前插入字符串
s.insert(3,4,'w') //在下标3前插入4个w
s1.swap(s2) //交换s1,s2的内容

s1.append(s2) //添加s2的内容到s1:s1="123",s2="abc",->s1="123abc"
s1.append(s2);  // s1 = "123abc"
s1.append(s2, 1, 2);  // s1 = "123bc"
s1.append(3, 'K');  // s1 = "123KKK"
s1.append("ABCDE", 2, 3);  // s1 = "123CDE",添加 "ABCDE" 的子串(2, 3)

s=s.replace(2,3,"aa") //用aa替换原来字符串的第2-3位,返回字符串
s=to_string(a) //把数值类型转化为string
int a=stoi(s1) //把string转化为数值类型int
float a=stof(s1) //把string转化为数值类型flloat

s1.assign(s2) //用s2给s1赋值
s1.assign(s2,2,3) //用s2的第2~3位给s1赋值
s1.assign(10,'c') //用10个c给s1赋值



可以用==运算符” + “、” [] “(下标运算符),处理string==

Vector(动态数组)

在C++中,加入了vector的类,可以随时改变数组的大小。

vector::push_back(x) //在容器最后一个位置插入元素x
vector::pop_back() //删除最后一个元素
vector::size() //返回元素个数
vector::capacity() //返回空间大小
vector::resize(n) //重新分配成员个数为n
vector::reserve(n) //重新分配空间大小为n
vector::clear() //清空容器内容,但空间没改变
vector::begin() //返回初始地址
vector::end() //返回结尾地址
    
vector::erase()//删除元素或⼀段序列
iterator erase(iterator position);
iterator erase(iterator first, iterator last);

vector::insert()//插⼊新的元素
iterator insert(iterator position, const T &x); //v.insert(v.begin()+1,3)在第1位前插入3
void insert(iterator position, size_type n, const T &x);
void insert(iterator position, InputIterator first, InputIterator last);
//第⼀个函数,在迭代器指定的位置前插⼊值为x的元素
//第⼆个函数,在迭代器指定的位置前插⼊n个值为x的元素
//第三个函数,在迭代器指定的位置前插⼊另外⼀个容器的⼀段序列迭代器first到last若插⼊新的元素后总得元素个数⼤于capacity,则重新分配空间

Vector常用方法
#include 
#include 

using namespace std;

int main()
{
    vector v = {7, 5, 16, 8};
    //push_back(),最后添加一个元素

    v.push_back(25);
    v.push_back(13);

    //成员函数size()、下标运算符[]
    for (int i = 0; i < v.size(); i++)
        cout << v[i] << '\t';
    cout << '\n';

    v.insert(v.begin()+1, 9); //插入不能用下标
    v.pop_back();

    for (int i = 0; i < v.size(); i++)
        cout << v[i] << '\t';
    cout << '\n';

    v.resize(2);

    for (int i = 0; i < v.size(); i++)
        cout << v[i] << '\t';
    cout << '\n';
}

案例:探索电脑分配内存是几倍分配的
#include 
#include 
#include 
using namespace std;
int main()
{
    vector a = {1, 2, 3};
    cout << "first" << a.capacity();
    a.push_back(3);
    a.push_back(4);
    a.push_back(5);
    cout << "second" << a.capacity();
    return 0;
}

8.指针和动态内存分配

指针

  • 指针变量就是存储指针(地址)的变量,如Type *P; //P是存储 ”Type类型变量的地址“ 的变量
  • 可以通过取内容运算符*得到一个指针变量指向的变量,如 *P就是P指向的那个变量
#include ;
using namespace std;
int main()
{
    int a = 1; // 作为test
    int *p = &a;
    cout << p << "\t" << &a << endl;
    cout << *p << "\t" << a << endl;
    int *q = p;
    cout << *p << "\t" << *q << endl;
    return 0;
}

动态内存分配

  • new 可以代替 malloc, 且会对对象进行初始化(在类中很有用)

  • int *p = new int; // p在函数的堆栈区,new在全局共享未使用堆存储区

  • delete可以代替free

    delete p; //释放p指向的内存,p本身没有被删掉。

    delete[] p; //释放==数组p==指向的内存

/* malloc free realloc 动态内存分配(在c中):new用于申请内存块、delete用于释放内存块 T *p = new T; delete p; T *q = new T[5]; delete[] q; */
// 堆存储区
#include 
using namespace std;

int main()
{
    int *p = new int;
    *p = 3;
    cout << p << '\t' << *p << endl;
    delete p;   //内存泄漏,释放p指向内存

    p = new int; //p又指向一个新的内存
    *p = 5;
    cout << p << '\t' << *p << endl;
    delete p;
}

9.类和对象

定义类的两种方法

用struct或class关键字定义一个类。定义的类就是一个数据类型。

struct student
{
	string name;
	double score;
}

class student{
private:
	string name;
	double score;
public: //接口
	void print() {cout << this->name << " " << this->score << endl;}
	string get_name() { return name; }
	double get_score() { return score; }
	void set_name(string n) { name = n; }
	void set_score(double s) { score = s; }
};

关于c/c++啥时候使用->或.运算符

可以参考这篇文章

【C、C++基础】什么时候用 “.” 什么时候用“->”(3个实例搞懂)_51CTO博客_什么时候用%c

注意点

注意:C语言中struct不能定义函数成员,而C++中可以,不过为了区分建议用class,且class有封装特性,自行决定成员公开还是私有struct默认所有成员公开!!!

案例

学生信息的录入:

#include 
using namespace std;
#include 
struct Student
{
    string name;
    double score;
    void print();
};
void Student::print()
{
    cout << name << "  " << score << endl;
}

int main()
{
    /*  Student stu;
     stu.name = "jack";
     stu.score = 122323;
     stu.print(); */
    vector<Student> students;
    while (1)
    {
        Student stu;
        cout << "请输入姓名 分数:\n";
        cin >> stu.name >> stu.score;
        if (stu.score < 0)
        {
            break;
        }
        students.push_back(stu);
    }
    cout << "人员信息为" << endl;
    for (int i = 0; i < students.size(); i++)
    {
        students[i].print();
    }

    return 0;
}

10.访问控制、基础函数

1.this指针

在c++中,类里面定义的成员函数,实际上==编译器会自动转化为外部函数,并带this指针==。

struct student{
	string name;
	double score;
    //void print(){cout << name << " " << score << endl;}; //函数声明
}
void print(student *this){//函数声明
	cout << this->name << " " << this->score << endl;
}; 
int main(){
    student stu;
    stu.name = "LI";
    stu.score = 88;
    stu.print(); // print(&stu) 会转化为指针参数
}

2.访问控制(封装)

private:私有的,只能通过==类体内==访问

public:公开的,可以在==类体外==访问

protected:受保护的,只能==在类体内访问==或在体外通过成员函数访问—不常用,了解即可。

#include 
using namespace std;
class Student
{
public:
    void print()
    {
        cout << this->name << "  " << this->age;
    }
    void setName(string n)
    {
        this->name = n;
    };
    void setAge(int x)
    {
        this->age = x;
    };
    string getname()
    {
        return this->name;
    };
    int getAge()
    {
        return this->age;
    };

private:
    string name;
    int age;
};

// main function test
int main()
{
    Student stu;
    stu.setAge(19);
    stu.setName("jack");
    stu.print();
    return -1;
}

3.构造函数(与java类似)

  • C++在创建一个类对象的时候,会自动调用被称为“构造函数”的成员函数
  • 如果没有定义构造函数,那么C++会自动生成一个构造函数:类名函数,且没有返回、没有形参,函数体里什么也不做
class student
{
    string name;
    double score;
public:
    student(string n, double s)name(n),score(s)//用列表初始化
    { 
        cout << "构造函数\n";
    }
}

/*等价于*/
    
class student
{
    string name;
    double score;
public:
    student(string n, double s){ 
        name = n;
        score = s;
        cout << "构造函数\n";
    }
}

在创建一个类对象的时候==会自动调用类函数==。

/* 构造函数: 函数名和类名相同且无返回类型的成员函数。 */
#include 
#include 
using namespace std;

class student
{
    string name;
    double score;
public:
    student(string n, double s)
    { //不是默认构造函数,重载
        name = n;
        score = s;
        cout << "构造函数\n";
    }
   
    student()
    {
        cout << "构造函数" << endl;
    }

    void print()
    {
        cout << this->name << " " << this->score << endl;
    }
};

int main()
{
    student stu("LiPing", 80.5); //在创建一个类对象时会自动调用称为“构造函数”的成员函数
    stu.print();
    student students[3];
}

构造函数小tips:

  • 当构造函数私有化后,就不能调用对象了。类似于构造有条件的三角形。
  • 调用构造函数==在声明的时候就会自动调用,java中是通过new==来创建的。
  • 列表序列化来声明。

4.拷贝构造函数、友元函数、析构函数

这几个有兴趣的,可以自行查阅资料,这里不深入探讨!

5.const修饰

基础:修饰变量

const int a=10;//a不可改

const int* a = &b://整型不可修改,但指针指向可以修改,*a不可改,a可改

int *const a = &b;//整型可修改,指针不可修改,*a可改,a不可改
 
const int *const p//二者都不可以改
    
void fun(const int i){}//i不能被修改

在类函数中使用

1.const修饰的函数,不能修改类中的成员变量,这是const修饰函数的基本作用

11.运算符重载(了解)

c++中允许对运算符进行重载,只要==他们的形参列表不一样==,例如输入的cin >> 输出的 cout <<

ostream& operator << (ostream &out, student s)//重载输出流
{
    cout << s.name << " "<< s.score << endl;
	return out;//引用,返回自身&,不加返回的是一个复制值
}

istream& operator>>(istream &in, student &s) //重载输入流,注意是引用s
{
	in >> s.name >> s.score;
	return in;
}

还有加法运算符,下标运算符重载。这里不过多赘述!!!

12.类模板(了解)

类模板的本质就是让类产生复用,通过泛型机制。前面所讲到的==vector==实际上就是一个类模板。下面我们手动封装一个类模板。

template //创建类模板
class Vector {
	T *data;
	int capacity;
	int n;
public:
	Vector(int cap=3) {
		data = new T[cap];//开辟的是3倍类型空间
		if (data == 0) {
			cap = 0; n = 0;
			return;
		}
		capacity = cap;
		n = 0;
	}
	void push_back(T e) {
		if (n == capacity) {//空间已经满
			cout << "增加容量!\n";
			T *p = new T[2 * capacity];
			if (p) {
				for (int i = 0; i < n; i++)
					p[i] = data[i];
				delete[] data;
				data = p;
				capacity = 2*capacity;
			}
			else {
				return;
			}
		}
		data[n] = e;
		n++;
	}
	T operator[](int i) const{
		if (i < 0 || i >= n) throw "下标非法!";
		return data[i];		
	}	
	int size() {
		return n;
	}
};

int main() {	
	Vector v; //可以定义任意类型变量
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(6);
	v.push_back(7);
	for (int i = 0; i < v.size(); i++)
		cout << v[i] << '\t';
	cout << endl;
}


13.类的继承

面向对象程序设计中最重要的一个概念是继承。继承允许我们依据另一个类来定义一个类,这使得创建和维护一个应用程序变得更容易。这样做,也达到了重用代码功能和提高执行效率的效果。这部分,如果了解过java的可以看一下语法即可。c++的继承原则:我们几乎不使用 protectedprivate 继承,通常使用 public 继承

单继承
class <派生类名>:<继承方式1><基类名1>
{
	<派生类类体>
};

#include 
 
using namespace std;
 
// 基类
class Shape 
{
   public:
      void setWidth(int w)
      {
         width = w;
      }
      void setHeight(int h)
      {
         height = h;
      }
   protected:
      int width;
      int height;
};
 
// 派生类
class Rectangle: public Shape
{
   public:
      int getArea()
      { 
         return (width * height); 
      }
};
 
int main(void)
{
   Rectangle Rect;
 
   Rect.setWidth(5);//通过成员函数访问受保护变量
   Rect.setHeight(7);
 
   // 输出对象的面积
   cout << "Total area: " << Rect.getArea() << endl;

   return 0;
}

多继承

c++的多继承机制也成为c++的特色之一。

class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,{
<派生类类体>
};

#include 

using namespace std;

// 基类 Shape
class Shape 
{
   public:
      void setWidth(int w)
      {
         width = w;
      }
      void setHeight(int h)
      {
         height = h;
      }
   protected:
      int width;
      int height;
};

// 基类 PaintCost
class PaintCost 
{
   public:
      int getCost(int area)
      {
         return area * 70;
      }
};

// 派生类
class Rectangle: public Shape, public PaintCost
{
   public:
      int getArea()
      { 
         return (width * height); 
      }
};

int main(void)
{
   Rectangle Rect;
   int area;

   Rect.setWidth(5);
   Rect.setHeight(7);

   area = Rect.getArea();

   // 输出对象的面积
   cout << "Total area: " << Rect.getArea() << endl;

   // 输出总花费
   cout << "Total paint cost: $" << Rect.getCost(area) << endl;

   return 0;
}

14.多态

关于c++面向对象的特征本文就讲述到这,本文的目的是帮助已经学过c的快速上手c++。以及了解c++的特性。如果大家想要继续深入c++的话,可以阅读c++官方文档或者阅读有关c++的书籍。✌✌✌✌✌

你可能感兴趣的:(c语言,c++,c语言)