概述
前言
看到本博最近都在学习机器学习,怎么突然冒出一篇C++的笔记,有点突兀……这是因为最近在学怎么获取数据,然后喂给机器学习算法,现在想从原始网络流量包中获取kdd99格式,网上找了下,有个现成的源码是使用C++写的,所以就花了半天时间看了下C++。
也就是说主要目的是为了看懂一个C++原程序,所以和C++相关的知识点是不全的,后续如有时间会再补充更新。
参考书籍《C++Primer.Plus(第6版)》
C++和C语言的主要区别是支持面向对象编程和泛型编程,本笔记不对C语言做记录,而仅记录C++的新特性。
Hello world
先有个直观认识。
运行环境:CentOS 5.4
新建名为hello.cpp的文件,内容如下:
#include <iostream>
int main(int argc, char **argv)#或者int main(void),或者int main()
{
std::cout << "hello world" << std::endl;
return 0;
}
编译和运行:
[root@ceshi03 c++]# g++ hello.cpp -o hello
[root@ceshi03 c++]# ./hello
hello world
[root@ceshi03 c++]#
不同编译器约定的语法不一样,常见的有:.cc、.cxx、.cpp、.cp以及.C
基本语法
基本语法主要列出和C语言不一样的内容。
输入输出
需要头文件
#include <iostream>
标准输入:std::cin
标准输出:std::cout
标准错误:std::cerr和std::clog
例子:
#include <iostream>
int main()
{
int a=0, b=0;
std::cin >> a >> b;
std::cout << "The num of " << a << " and " << b
<< " is " << a+b << std::endl;
return 0;
}
[root@ceshi03 c++]# g++ std.cpp
[root@ceshi03 c++]# ./a.out
2 3
The num of 2 and 3 is 5
>>:输入运算符
<<:输出运算符
默认参数
char * left(const char * str, int n = 1);
函数重载(函数多态)
函数重载和函数多态是同一概念,它支持多个相同的函数名定义,但其形参变量类型或个数不一样,最简单的代码如下所示,其还有一些细节上需要注意的地方,比如哪些可以重载,哪些不可以重载。
#include <iostream>
using namespace std;
//交换 int 变量的值
void Swap(int *a, int *b){
int temp = *a;
*a = *b;
*b = temp;
}
//交换 float 变量的值
void Swap(float *a, float *b){
float temp = *a;
*a = *b;
*b = temp;
}
//交换 char 变量的值
void Swap(char *a, char *b){
char temp = *a;
*a = *b;
*b = temp;
}
//交换 bool 变量的值
void Swap(bool *a, bool *b){
char temp = *a;
*a = *b;
*b = temp;
}
int main(){
//交换 int 变量的值
int n1 = 100, n2 = 200;
Swap(&n1, &n2);
cout<<n1<<", "<<n2<<endl;
//交换 float 变量的值
float f1 = 12.5, f2 = 56.93;
Swap(&f1, &f2);
cout<<f1<<", "<<f2<<endl;
//交换 char 变量的值
char c1 = 'A', c2 = 'B';
Swap(&c1, &c2);
cout<<c1<<", "<<c2<<endl;
//交换 bool 变量的值
bool b1 = false, b2 = true;
Swap(&b1, &b2);
cout<<b1<<", "<<b2<<endl;
return 0;
}
函数模板
在C语言中如果要交换两个int,两个double就要定义两个函数,C++就可以使用函数模板解决这个问题。
定义一个模板:
template <typename AnyType>
关键字template和typename是必须的,typename位置也可使用class,另外必须使用尖括号,类型名AnyType可以任意选择,只要符合C++命名规范即可,一般常用T来命名。
如下代码演示了模板的使用,它通过调用的地方传入不同类型的变量来决定T的类型,而最终生成带什么类型的函数由编译器完成。
#include <iostream>
// function template prototype
template <typename T>
// or class T
void Swap(T &a, T &b);
int main()
{
using namespace std;
int i = 10;
int j = 20;
cout << "i, j = " << i << ", " << j << ".n";
cout << "Using compiler-generated int swapper:n";
Swap(i,j);
// generates void Swap(int &, int &)
cout << "Now i, j = " << i << ", " << j << ".n";
double x = 24.5;
double y = 81.7;
cout << "x, y = " << x << ", " << y << ".n";
cout << "Using compiler-generated double swapper:n";
Swap(x,y);
// generates void Swap(double &, double &)
cout << "Now x, y = " << x << ", " << y << ".n";
// cin.get();
return 0;
}
// function template definition
template <typename T>
// or class T
void Swap(T &a, T &b)
{
T temp;
// temp a variable of type T
temp = a;
a = b;
b = temp;
}
模板重载
原来的模板类型为(T &, T&),新模板的类型为(T , T , int)。从中也可以知道模板参数并非一定是模板参数类型,而是可以是具体的类型。
#include <iostream>
template <typename T>
// original template
void Swap(T &a, T &b);
template <typename T>
// new template
void Swap(T *a, T *b, int n);
void Show(int a[]);
const int Lim = 8;
int main()
{
using namespace std;
int i = 10, j = 20;
cout << "i, j = " << i << ", " << j << ".n";
cout << "Using compiler-generated int swapper:n";
Swap(i,j);
// matches original template
cout << "Now i, j = " << i << ", " << j << ".n";
int d1[Lim] = {0,7,0,4,1,7,7,6};
int d2[Lim] = {0,7,2,0,1,9,6,9};
cout << "Original arrays:n";
Show(d1);
Show(d2);
Swap(d1,d2,Lim);
// matches new template
cout << "Swapped arrays:n";
Show(d1);
Show(d2);
// cin.get();
return 0;
}
template <typename T>
void Swap(T &a, T &b)
{
T temp;
temp = a;
a = b;
b = temp;
}
template <typename T>
void Swap(T a[], T b[], int n)
{
T temp;
for (int i = 0; i < n; i++)
{
temp = a[i];
a[i] = b[i];
b[i] = temp;
}
}
void Show(int a[])
{
using namespace std;
cout << a[0] << a[1] << "/";
cout << a[2] << a[3] << "/";
for (int i = 4; i < Lim; i++)
cout << a[i];
cout << endl;
}
显示具体化(explicit specialization)
如果有多个原型,则编译器在选择原型时,非模板版本优先显示具体化和模板版本,而显示具体化优先模板版本。
#include <iostream>
template <typename T>
void Swap(T &a, T &b);
struct job
{
char name[40];
double salary;
int floor;
};
// explicit specialization
template <> void Swap<job>(job &j1, job &j2);
void Show(job &j);
int main()
{
using namespace std;
cout.precision(2);
cout.setf(ios::fixed, ios::floatfield);
int i = 10, j = 20;
cout << "i, j = " << i << ", " << j << ".n";
cout << "Using compiler-generated int swapper:n";
Swap(i,j);
// generates void Swap(int &, int &)
cout << "Now i, j = " << i << ", " << j << ".n";
job sue = {"Susan Yaffee", 73000.60, 7};
job sidney = {"Sidney Taffee", 78060.72, 9};
cout << "Before job swapping:n";
Show(sue);
Show(sidney);
Swap(sue, sidney); // uses void Swap(job &, job &)
cout << "After job swapping:n";
Show(sue);
Show(sidney);
// cin.get();
return 0;
}
template <typename T>
void Swap(T &a, T &b)
// general version
{
T temp;
temp = a;
a = b;
b = temp;
}
// swaps just the salary and floor fields of a job structure
template <> void Swap<job>(job &j1, job &j2)
// specialization
{
double t1;
int t2;
t1 = j1.salary;
j1.salary = j2.salary;
j2.salary = t1;
t2 = j1.floor;
j1.floor = j2.floor;
j2.floor = t2;
}
void Show(job &j)
{
using namespace std;
cout << j.name << ": $" << j.salary
<< " on floor " << j.floor << endl;
}
实例化
之前的例子在调用Swap(i,j)时传入的i,j为int类型,生成一个Swap()的实例,这种实例化称为隐式实例化。C++还允许显示实例化(explicit instantiation),可通过类似的语法:Swap(),其声明所需的种类用<>符号指示类型,并在声明前加上template:
template void Swap<int>(int, int);
对象和类
面向对象编程(OOP)主要特性:
- 抽象
- 封装和数据隐藏
- 多态
- 继承
- 代码的可重用性
C++中的类
定义一个类
文件名:stock00.h
#ifndef STOCK00_H_
#define STOCK00_H_
#include <string>
class Stock
// class declaration
{
private:
std::string company;
long shares;
double share_val;
double total_val;
void set_tot() { total_val = shares * share_val; }
public:
void acquire(const std::string & co, long n, double pr);
void buy(long num, double price);
void sell(long num, double price);
void update(double price);
void show();
};
// note semicolon at the end
#endif
使用类对象的程序可直接访问public部分,但只能通过public函数(或友元函数)来访问对象中的private成员。
实现类成员函数(双冒号::)
#include <iostream>
#include "stock00.h"
void Stock::acquire(const std::string & co, long n, double pr)
{
company = co;
if (n < 0)
{
std::cout << "Number of shares can't be negative; "
<< company << " shares set to 0.n";
shares = 0;
}
else
shares = n;
share_val = pr;
set_tot();
}
void Stock::buy(long num, double price)
{
if (num < 0)
{
std::cout << "Number of shares purchased can't be negative. "
<< "Transaction is aborted.n";
}
else
{
shares += num;
share_val = price;
set_tot();
}
}
void Stock::sell(long num, double price)
{
using std::cout;
if (num < 0)
{
cout << "Number of shares sold can't be negative. "
<< "Transaction is aborted.n";
}
else if (num > shares)
{
cout << "You can't sell more than you have! "
<< "Transaction is aborted.n";
}
else
{
shares -= num;
share_val = price;
set_tot();
}
}
void Stock::update(double price)
{
share_val = price;
set_tot();
}
void Stock::show()
{
std::cout << "Company: " << company
<< "
Shares: " << shares << 'n'
<< "
Share Price: $" << share_val
<< "
Total Worth: $" << total_val << 'n';
}
构造函数和析构函数
具体请看例子
#include <iostream>
#include "stock10.h"
// constructors (verbose versions)
Stock::Stock()
//默认构造函数
{
std::cout << "Default constructor calledn";
company = "no name";
shares = 0;
share_val = 0.0;
total_val = 0.0;
}
Stock::Stock(const std::string & co, long n, double pr)
{
std::cout << "Constructor using " << co << " calledn";
company = co;
if (n < 0)
{
std::cout << "Number of shares can't be negative; "
<< company << " shares set to 0.n";
shares = 0;
}
else
shares = n;
share_val = pr;
set_tot();
}
// class destructor
Stock::~Stock()
//析构函数
{
std::cout << "Bye, " << company << "!n";
}
// other methods
void Stock::buy(long num, double price)
{
if (num < 0)
{
std::cout << "Number of shares purchased can't be negative. "
<< "Transaction is aborted.n";
}
else
{
shares += num;
share_val = price;
set_tot();
}
}
void Stock::sell(long num, double price)
{
using std::cout;
if (num < 0)
{
cout << "Number of shares sold can't be negative. "
<< "Transaction is aborted.n";
}
else if (num > shares)
{
cout << "You can't sell more than you have! "
<< "Transaction is aborted.n";
}
else
{
shares -= num;
share_val = price;
set_tot();
}
}
void Stock::update(double price)
{
share_val = price;
set_tot();
}
void Stock::show()
{
using std::cout;
using std::ios_base;
// set format to #.###
ios_base::fmtflags orig =
cout.setf(ios_base::fixed, ios_base::floatfield);
std::streamsize prec = cout.precision(3);
cout << "Company: " << company
<< "
Shares: " << shares << 'n';
cout << "
Share Price: $" << share_val;
// set format to #.##
cout.precision(2);
cout << "
Total Worth: $" << total_val << 'n';
// restore original format
cout.setf(orig, ios_base::floatfield);
cout.precision(prec);
}
构造函数的形参名不能和成员名一样,比如如下代码是错误的:
Stock::Stock(const stirng &company, long shares, double share_val)
为避免这种混乱,一种方法是在数据成员中使用m_ 前缀,或者使用 _ 后缀,比如
class Stock
// class declaration
{
private:
std::string m_company;
long m_shares;
double m_share_val;
double m_total_val;
……
或者
class Stock
// class declaration
{
private:
std::string company_;
long shares_;
double share_val_;
double total_val_;
……
C++ this
this 是 C++ 中的一个关键字,也是一个 const 指针,它指向当前对象,通过它可以访问当前对象的所有成员。
#include <iostream>
using namespace std;
class Student{
public:
void setname(char *name);
void setage(int age);
void setscore(float score);
void show();
private:
char *name;
int age;
float score;
};
void Student::setname(char *name){
this->name = name;
}
void Student::setage(int age){
this->age = age;
}
void Student::setscore(float score){
this->score = score;
}
void Student::show(){
cout<<this->name<<"的年龄是"<<this->age<<",成绩是"<<this->score<<endl;
}
int main(){
Student *pstu = new Student;
pstu -> setname("李华");
pstu -> setage(16);
pstu -> setscore(96.5);
pstu -> show();
return 0;
}
最后
以上就是无情天空为你收集整理的c++学习笔记前言Hello world基本语法对象和类的全部内容,希望文章能够帮你解决c++学习笔记前言Hello world基本语法对象和类所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复