C++笔记(没图解个人用)

        学C++也有大半个月了,先来总结下目前为止学了什么.

        首先 c是面向过程,c是以为函数为中心,数据做为函数的参数来进行处理;c++是面向对象的。c++是以数据为中心,函数只是数据的一个部分。
 c++只要搞清楚一个以数据为中心,其它的都可以理解为c++的数据服务的
但也要清楚,在项目中并不去严格区分面向过程或面向对象。程序严格的讲就是一个流程式的操作的,面向对象只不过是让项目的管理更加的方便而已
所以不要区分的太死,一定是面向过程或一定是面向对象.
        (1)命名空间 关键字:namespace 主要是更好的管理程序,分类程序,使程序看起来更有条理.
             用法:namespace  Sort //标识符
             {
                 // 各种功能
                void   QuickSort();//声明,可以外部实现
                void    HIitSort();
              }
             void Sort::QuickSort()
              {
                    //函数体
               }
                void Sort::HIitSort()
              {
                    //函数体
               }
              命名空间支持嵌套使用
             还有三种去头的用法以及区别:
            (a):using namespace Sort;
              自开始位置往下所有这个Sort空间下的工具都可以不写域名
            (b):using Sort::QuickSort;
                 自开始位置往下用到QuickSort这个工具都可以不用写域名,但是其他的还是要写,只是当解锁了他的权限
            (c):多层嵌套时可以用namespace AB=Sort::Funcation::sdfds;
            举个例子:

// stdafx.h : 标准系统包含文件的包含文件,

// 或是经常使用但不常更改的

// 特定于项目的包含文件

//

 

#pragma once

 

#include "targetver.h"

#include<cstdlib>

#include <stdio.h>

#include <tchar.h>

#include<cstring>

#include<iostream>

using namespace std;

namespace Function//功能

{

namespace Sort//排序

{

void QuickSort(int arr[], int left, int right);//快排

void HillSort(int arr[], int len);//希尔排序

}

namespace KMP//快速查找字符串

{

void GetNext(char *str, int nextval[]);//跳转数组

int Kmp(char *str1, char *str2);//kmp算法

}

namespace Show//打印函数

{

void Show(int*Arr, int len);

}

}

 

 

// TODO:  在此处引用程序需要的其他头文件

 

// 第二次作业.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"

void Function::Sort::QuickSort(int arr[], int left, int right)//快速排序

{

int low = left;

int high = right;

int temp = arr[left];//挖第一个坑

if (left > right)//递归出口

{

return;

}

while (low != high)

{

for (; low<high&&arr[high]>temp; high--){}

if (low < high)

{

arr[low++] = arr[high];//满足条件填左边的坑同时又在右边挖一个坑

}

for (; low < high&&arr[low] < temp; low++){}

if (low < high)

{

arr[high--] = arr[low];//又满足条件填右边的坑同时又给左边挖一个坑

}

}

arr[high] = temp;//当左右指针相同,吧最开始挖出来的东西填在这个坑

QuickSort(arr, left, high - 1);//左半部

QuickSort(arr, high + 1, right);//右半部

}

void Function::Sort::HillSort(int arr[], int len)//希尔排序

{

int gap;

for (gap = len / 2; gap > 0; gap /= 2)//确定步长.分成gap个组,分别进行插入排序

{

for (int i = gap; i < len; ++i)

{

for (int j = i - gap; j >= 0 && arr[j]>arr[j + gap]; j -= gap)//插入排序

{

arr[j] ^= arr[j + gap];

arr[j + gap] ^= arr[j];

arr[j] ^= arr[j + gap];

}

}

}

}

void Function::KMP::GetNext(char *str, int nextval[])//next跳转数组,直接跳过相同的

{

unsigned int i = 0;

int j = -1;

nextval[0] = -1;

while (i < strlen(str))

{

if (j == -1 || str[i] == str[j])

{

i++;

j++;

nextval[i] = j;

}

else

/*j = nextval[j];*/

j = -1;

}

}

int Function::KMP::Kmp(char *str1, char *str2)//kmp算法

{

int i = 0;

int  j = 0;

int* nextval = (int*)calloc(100, sizeof(int));

int lenstr1 = strlen(str1);

int lenstr2 = strlen(str2);

GetNext(str2, nextval);

while ((i < lenstr1) && (j < lenstr2))

{

if (j == -1 || str1[i] == str2[j])

{

i++;

j++;

}

else

j = nextval[j];

if (j == lenstr2 || j == lenstr1)

{

free(nextval);

return i - lenstr2;

}

}

free(nextval);

return -1;

}

void Function::Show::Show(int*Arr,int len)//打印函数

{

for (int i = 0; i < len; ++i)

{

cout << Arr[i] << endl;

}

}

int _tmain(int argc, _TCHAR* argv[])

{

int Arr[10] = { 1, 5655, 6565, 56, 56, 55481, 77, 87877, 8, 78 };

int Arr2[10] = { 1, 58, 54, 7, 8, 8,  7887, 88, 8 ,10};

Function::Sort::QuickSort(Arr, 0, 9);

Function::Sort::HillSort(Arr2, 10);

    Function::Show::Show(Arr,10);

Function::Show::Show(Arr2,10);

int NEXT[32] = { 0 };

char Name[32] = "jdfhjfkdkfdjfhjdshfjdshjfh";

char  name[32] = "djfh";

Function::KMP::GetNext(name, NEXT);

if (Function::KMP::Kmp(Name, name) != -1)

{

cout << "查找成功位置在:"<<Function::KMP::Kmp(Name,name) << endl;

}

system("pause");

return 0;

}

(2)类的定义   关键字 class

 class   mm//标识符

{

//此处默认私有属性

public://公有属性   公有接口,通过对象可以直接访问

mm(){}//构造函数  用来初始化 (两种出事化方式)数据成员,在构造对象是自动调用

~mm(){}//析构函数 对象死亡时自动调用,此处注意如果类中使用了堆区内存,就需要自己写析构函数,否则有默认析构函数

protected://保护属性  和私有属性一样都不能被对象在类外访问

private://私有属性      同上,与保护类型区别在于继承多态这块

}

这里提一下内联函数,内联函数即inline修饰的函数,在预编译时会将inline修饰的函数直接加入主函数,优点减少时间复杂度避免常用代码重复调用浪费时间,不过最好不要修饰代码量多的函数.否则适得其反,在类中实现函数,即默认为内联函数.

(3)const 修饰的数据成员,成员函数,对象;static 修饰的变量, 函数,以及友元函数

(a)const

    类中const 修饰数据成员,必须通过初始化参数列表的方式初始化,且一经初始化不能修改

    类中const修饰成员函数时必须加在函数参数列表后进行修饰,原因加在前面会被默认为返回类型,const函数中的this指针所指的数据成员都不能修改(this指针是系统默认指对象的指针)

    类外创建对象时用const修饰时,即常量对象,该对象只能访问const修饰的成员函数.

(b)static

    类中static修饰变量,该变量存在全局区,不属于任何对象但属于这个类,能被所有对象共享,可以用来计数等.

    类中static修饰的函数,该函数也是不属于单个对象属于这个类,该函数只能访问静态数据,不能直接访问类中成员数据,因为没有this指针(只能通过传参对象的引用并要有接口)

    类中其他成员函数都可以随意访问静态变量和函数.

(c)友元   关键字friend   友元是一种打破类封装性的工具.

     friend修饰的函数称为友元函数,首先它不属于类是个普通函数,外部访问不需要加域名加以限定,友元函数内部通过传参该类对象的引用,能直接访问私有数据而不需要接口函数

     注意友元不具有传递性,单向,不能被继承(注意在任意属性下声明都一样).

    friend class Sort,即友元类的声明,可以理解为友元类中的所有成员函数都是另一个类的友元函数.

例子:

#include<iostream>
using namespace std;
class A
{
public:
A(int x=0, int y=0) :x(x), y(y){}
friend void show(A & b);
protected:
friend class B;
private:
int x;
int y;
};
void show(A & b)//注意友元函数不属于类不需要void A::show();这样实现
{
cout <<b. x <<b. y << endl;
}
class B
{
public:
B(int d = 0, int f = 0) :d(d), f(f){}
void show(A& a)
{
cout << d << f << endl;
cout << a.x << a.y << endl;
}
protected:
private:
int d;
int f;
};
int main()
{
A d(2,3);
show(d);
B g(5,6);
g.show(d);
system("pause");
return 0;
}

(4)继承 说到底也是为了程序更具条理性,能更好的管理维护,继承即一个类去继承另一个类的所有属性,注意三种属性继承,分别为public,protected,private,哪种属性继承的最高权限就是哪个属性.

    下面举个例子:

//这里举个菱形继承结构的例子,多层复杂继承关系,
#include<iostream>
using namespace std;
//class A
//{
//public:
// A(int x=0, int y=0) :x(x), y(y){}
// void show()
// {
// cout << x << y << endl;
// }
//protected:
//private:
// int x;
// int y;
// //占8字节
//};
//class B :public A
//{
//public:
// B(int d = 0, int f = 0) :d(d), f(f){}
// void show()
// {
// cout << d << f << endl;
// }
// int d;
// int f;
// //占16字节
//};
//class D :public A
//{
//public:
// D(int c = 0, int k = 0) :c(c), k(k){}
// void show()
// {
// cout << c << k << endl;
// }
// int c;
// int k;
// //占16字节
//};
//class F :public B, public D
//{
//public:
// F(int i = 0, int o = 0) :i(i), o(o){}
// void show()
// {
// cout << i << o << endl;
// }
// int i;
// int o;
// //占40字节
//};
class A
{
public:
A(int x = 0, int y = 0) :x(x), y(y){}
void show()
{
cout << x << y << endl;
}
protected:
private:
int x;
int y;
//占8字节
};
class B : virtual  public A
{
public:
B(int d = 0, int f = 0) :d(d), f(f){}
void show()
{
cout << d << f << endl;
}
int d;
int f;
//占20字节
};
class D : virtual public A
{
public:
D(int c = 0, int k = 0) :c(c), k(k){}
void show()
{
cout << c << k << endl;
}
int c;
int k;
//占20字节
};
class F :public B, public D
{
public:
F(int i = 0, int o = 0) :i(i), o(o){}
void show()
{
cout << i << o << endl;
}
int i;
int o;
//占40字节
};
int main()
{
A d;
B f;
D t;
F a;
cout << sizeof(d) << endl;
cout << sizeof(f) << endl;
cout << sizeof(t) << endl;
cout << sizeof(a) << endl;
/*注意构造派生类F时会构造两次A,加大了浪费时间和空间复杂度,且访问A类属性会产生二义性
避免二义性,一种是通过B和D的域名加以限定,还有就是通过virtual关键字修饰(即虚继承)
总之虚继承就是防止A被继承两次,
这里再说一下继承顺序吧,有点类似递归,有个口诀就是,构造一个类时先判断是否有基类有先构造基类,没有判断有无子对象,有先构造子对象,最后构造本身,构造基类和子对象          时递归这个操作,
比如这个例子:构造顺序为ABADF
这里再提一下虚这个概念,virtual,你可以理解为一个抽象出来的指针,在这种菱形复杂继承时一般都使用虚继承,节约空间.
(在类中只要有virtual该类实例化就会多4字节,且在 类内存的前端)
只要有虚继承,继承顺序:继承链中只要有虚继承,毫无道理的先构造虚基类,然后按之前的构造顺序,如果遇到virtual就通过这个指针去判断是否已经构造如果已经构造就通过           没有构造下面的,即ABDF,减少一次A的构造,这里注意A就不是由BD间接构造的了,而是由派生类F直接构造,所以如果虚基类必须带参构造时,
F也要给A传参(注意虚基类的内存一定是在整个派生类内存的末端,这个可以自己去尝试)*/
system("pause");
return 0;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值