C++之旅(第一天)
基础知识
完全支持C语言
可以在C++引入C的头文件
#include <stdio.h>
#include <iostream>
int main() {
}
输入和输出
C++中的输入使用cin,输出使用cout
#include <stdio.h>
#include <iostream>
int main() {
int i;
//C++中的输入和输出
std::cin >> i;
std::cout << i << std::endl;
//C中的输入和输出
scanf("%d", &i);
printf("%d\n", i);
}
名字空间
为了在大型项目开发中解决类,函数命名冲突问题而引入了namespace。下面的代码中引入了C++中的标准库命名空间std,这样我们就不用在cin,cout,endl前面添加命名空间了
#include <iostream>
using namespace std;
namespace outer {
void outerTest() {
cout << "this is outer namespace" << endl;
}
}
int main() {
outer::outerTest();
}
结构体和类
结构体成员默认对外开放,随时随地都可以访问。class中的成员默认私有,无法直接访问。这里的struct和class一样,内部可以使用权限修饰符,函数等。
#include <iostream>
struct man {
int age;
int sex;
};
class man2 {
int age;
int sex;
};
int main() {
man m;
m.age = 10; // 可以正常赋值
m.sex = 0; // 可以正常赋值
man2 man2;
man2.age = 11; // 编译报错
man2.sex = 1; // 编译报错
}
对象的分配
通过new创建对象,通过delete释放对象,注意数组的释放有点特殊;
int main() {
int* p1 = new int();
int* p2 = new int[10];
delete p1;
delete []p2;
}
引用
引用不是地址,只是变量的别名,引用不占用空间,引用只能被初始化一次且在声明时初始化。
#include <iostream>
#include <stdio.h>
using namespace std;
void mSwap (int &a, int &b) {
int tmp;
tmp = a;
a = b;
b = tmp;
}
int main() {
int a = 10;
int b = 5;
mSwap(a, b); //交换成功
cout << a << b << endl;
//引用在声明时必须被初始化且不能更改
int& c = a;
//输出的值一致,所以引用不占空间
printf("c地址为:%p, a地址为:%p\n", &c, &b);
}
在值传递的情况下,void mSwap (int a, int b)它会将传入的参数拷贝一份,然后在自己的栈帧内对拷贝的数据进行操作。而使用引用传递void mSwap (int& a, int& b)则会直接操作main函数栈帧上的变量,所以后者能交换成功,这就是跨栈操作。如果希望传递引用又不想被修改可以使用下面方式
void mSwap (const int &a) {
cout << a << endl;
}
缺省参数
#include <iostream>
using namespace std;
void m (int a = 10) {
cout << a << endl;
}
int main() {
m(); // 输出10
m(11); // 输出11
}
模版
模版在对不同数据做相同操作时用到,其核心就是泛型。下面就是一个模版函数的使用,可以支持整型和浮点的加操作
#include <iostream>
using namespace std;
template <class T>
T myadd(T a, T b) {
return a + b;
}
int main() {
cout << myadd(1, 2) << endl;
cout << myadd(1.0, 3.0) << endl;
}
指针常量与常量指针
指针常量:指针是个常量,不能修改指针的值;常量指针:指针指向的位置是个常量(在指针看来),不能通过指针修改其值
int main() {
int a=0;
int b = 1;
// 指针常量,p的值不能被修改
int* const p = &a;
p = &b; //编译错误,不能修改p的值
*p = 10;
// 常量指针,p1的值可以被修改
const int* p1 = &a;
p1 = &b;
*p1 = 10; //编译错误,不能通过指针p1修改其指向的值
a = 11;
b = 12;
}
类的初始化
man.h文件中声明一个类
#ifndef MAN_H
#define MAN_H
#include <string>
using namespace std;
class Man {
public:
Man();
~Man();
protected:
private:
int& a;
int b;
string name;
const int age;
};
#endif // MAN_H
man.cpp中初始化成员
#include "man.h"
Man::Man():age(10),a(b) { // 注意常量,引用必须在成员列表初始化
name = "tom";
}
Man::~Man() {
//dtor
}
拷贝
拷贝一般应实现拷贝函数,如果未实现则采用默认拷贝函数
class Test {
public:
Test(const Test& t); //自定义拷贝函数
}
Test t1;
Test t2 = t1; //调用拷贝函数
静态变量与静态成员
在C中一个变量被static修饰后,这个变量将处于静态数据区。比如下面的代码,程序被加载到内存后,只有当test1被调用后变量a才会被创建(在栈上创建)。但是对于test2而言,程序一旦被加载,即使没有调用test2,变量a都存在了。
void test1(){
int a = 0;
}
void test2() {
static int a = 0;
}
C++中的静态成员属于类成员,只要类被加载了,该成员就就会在内存中被创建出来。
静态成员只能在类外部被初始化。
Man.h文件中声明类
class Man
{
public:
Man();
~Man();
static int a;
};
Man.cpp
#include "Man.h"
int Man::a = 100; //对静态成员初始化
Man::Man()
{
}
Man::~Man()
{
}
数组的初始化
定义一个对象数组
int main(int argc, char **argv) {
//调用无参构造函数
Man man[3];
//调用有参构造函数
Man man2[3] = {Man(1), Man(2), Man(3)};
}
实践
MyString.h
#ifndef MYSTRING_H
#define MYSTRING_H
namespace xdysite {
class MyString {
public:
MyString(const char* str);
~MyString();
MyString(const MyString& myString);
const char* getString();
void setString(const char* str);
private:
char* str;
};
}
#endif // MYSTRING_H
MyString.cpp
#include "MyString.h"
#include <algorithm>
#include <cstring>
using namespace std;
xdysite::MyString::MyString(const char* str) {
int len = strlen(str);
this->str = new char[len + 1];
strncpy(this->str, str, len);
}
xdysite::MyString::~MyString() {
delete []str;
str = NULL;
}
xdysite::MyString::MyString(const MyString& myString) {
int len = strlen(myString.str);
str = new char[len + 1];
strncpy(str, myString.str, len);
}
const char* xdysite::MyString::getString() {
return str;
}
void xdysite::MyString::setString(const char* str) {
int len1 = strlen(str);
int len2 = strlen(this->str);
if(len2 >= len1)
strncpy(this->str, str, len1);
else {
delete []this->str;
this->str = new char[len1 + 1];
strncpy(this->str, str, len1);
}
}
man.cpp
#include <iostream>
#include "MyString.h"
using namespace std;
using namespace xdysite;
int main(int argc, char **argv) {
MyString myString = "hello world!";
MyString myString2 = myString;
myString.setString("HELLO");
cout << myString2.getString() << endl;
}