作者有个自己的想法,如果C语言编写开发中,能把面向对象的思想添加进去,可以让代码更加美观,更加简洁,特别是代码复用。要让代码实现《高内聚、低耦合》,这样写代码才比较有意义。工作一年后,发现读大学的时候,做项目的代码感觉就像一坨shi一样。只要想到什么就写什么,完全没有代码复用的概念。
C 基础知识说明,如果你学过C语言,那么基础知识是一样的,比循环、运算符、指针等…。可以说C 是在C的基础上增加了面向对象编程。在C语言中,也可以实现类似面向对象的实现,实现代码的重用。
C 类定义:
类是面向对象程序设计实现信息封装的基础。类定义以关键字class开头,后跟类名。
以下例子:定义了一个temp类,包含两个成员变量和一个方法函数,main()中,定义temp的对象temp1,然后可以直接访问类中的公有成员。
代码语言:javascript复制#include <iostream>
class temp
{
public:
int x;
int y;
int add(int a, int b)
{
return (a b);
}
};
int main()
{
temp temp1;
temp1.x = 10;
temp1.y = 20;
std::cout << "Temp1 return value:" << temp1.add(temp1.x, temp1.y) << std::endl;
return 0;
}
其中:在c语言中,可以通过结构体来实现类这个概念。
代码语言:javascript复制#include <stdio.h>
struct temp
{
int x;
int y;
int(*add)(int a, int b);
};
int add(int a, int b)
{
return a b;
}
int main()
{
struct temp temp1;
temp1.x = 10;
temp1.y = 20;
temp1.add = add;
printf("Temp1 return value:%d", temp1.add(temp1.x, temp1.y));
return 0;
}
C 继承:
面向对象程序设计中最重要的一个概念是继承。继承允许我们依据另一个类来定义一个类,这使得创建和维护一个应用程序变得更容易。这样做,也达到了重用代码功能和提高执行时间的效果。C 支持多继承。
以下例子:定义了一个基类base,定义了一个子类sum,子类继承了基类base,
代码语言:javascript复制#include <iostream>
class base
{
public:
int x;
int y;
};
class sum: public base
{
public:
int add()
{
return (x y);
}
};
int main()
{
sum sum1;
sum1.x = 10;
sum1.y = 20;
std::cout << "Temp1 return value:" << sum1.add() << std::endl;
return 0;
}
注意:派生类可以访问基类中所有的非私有成员。因此基类成员如果不想被派生类的成员函数访问,则应在基类中声明为 private。
我们可以根据访问权限总结出不同的访问类型,如下所示:
访问 | public | protected | private |
---|---|---|---|
同一个类 | yes | yes | yes |
派生类 | yes | yes | no |
外部的类 | yes | no | no |
一个派生类继承了所有的基类方法,但下列情况除外:
1.基类的构造函数、析构函数和拷贝构造函数。
2.基类的重载运算符。
3.基类的友元函数。
继承类型:当一个类派生自基类,该基类可以被继承为 public、protected 或 private 几种类型。继承类型是通过上面讲解的访问修饰符 access-specifier 来指定的。我们几乎不使用 protected 或 private 继承,通常使用 public 继承。当使用不同类型的继承时,遵循以下几个规则:
公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。
保护继承(protected): 当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员。
私有继承(private):当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员。
其中:在c语言中,可以通过结构体来实现继承这个概念。
代码语言:javascript复制#include <stdio.h>
struct base
{
int x;
int y;
};
struct sum
{
struct base base1;
int(*add)(int a, int b);
};
int add(int a, int b)
{
return a b;
}
int main()
{
struct sum sum1;
sum1.base1.x = 10;
sum1.base1.y = 20;
sum1.add = add;
printf("Temp1 return value:%d", sum1.add(sum1.base1.x, sum1.base1.y));
return 0;
}
C 重载:
C 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载。
重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同。
当您调用一个重载函数或重载运算符时,编译器通过把您所使用的参数类型与定义中的参数类型进行比较,决定选用最合适的定义。选择最合适的重载函数或重载运算符的过程,称为重载决策。
函数重载:在同一个作用域内,可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同。您不能仅通过返回类型的不同来重载函数。
以下例子:类中定义了两个同名函数print,参数不同,一个为int,一个是double,
代码语言:javascript复制#include <iostream>
class print_data
{
public:
void print(int i)
{
std::cout << "int:" << i << std::endl;
}
void print(double f)
{
std::cout << "double:" << f << std::endl;
}
};
int main()
{
print_data pd;
pd.print(10);
pd.print(13.14);
return 0;
}
运算符重载:重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。
代码语言:javascript复制#include <iostream>
class Box
{
public:
double getVolume(void)
{
return length * breadth * height;
}
void setLength(double len)
{
length = len;
}
void setBreadth(double bre)
{
breadth = bre;
}
void setHeight(double hei)
{
height = hei;
}
Box operator (const Box& b)
{
Box box;
box.length = this->length b.length;
box.breadth = this->breadth b.breadth;
box.height = this->height b.height;
return box;
}
private:
double length;
double breadth;
double height;
};
int main()
{
Box Box1;
Box Box2;
Box Box3;
double volume = 0.0;
Box1.setLength(6.0);
Box1.setBreadth(7.0);
Box1.setHeight(5.0);
Box2.setLength(12.0);
Box2.setBreadth(13.0);
Box2.setHeight(10.0);
volume = Box1.getVolume();
std::cout << "Volume of Box1 : " << volume << std::endl;
volume = Box2.getVolume();
std::cout << "Volume of Box2 : " << volume << std::endl;
Box3 = Box1 Box2;
volume = Box3.getVolume();
std::cout << "Volume of Box3 : " << volume << std::endl;
return 0;
}
可重载运算符:
双目算术运算符 | (加),-(减),*(乘),/(除),% (取模) |
---|---|
关系运算符 | ==(等于),!= (不等于),< (小于),> (大于>,<=(小于等于),>=(大于等于) |
逻辑运算符 | ||(逻辑或),&&(逻辑与),!(逻辑非) |
单目运算符 | (正),-(负),*(指针),&(取地址) |
自增自减运算符 | (自增),--(自减) |
位运算符 | | (按位或),& (按位与),~(按位取反),^(按位异或),,<< (左移),>>(右移) |
赋值运算符 | =, =, -=, *=, /= , % = , &=, |=, ^=, <<=, >>= |
空间申请与释放 | new, delete, new[ ] , delete[] |
其他运算符 | ()(函数调用),->(成员访问),,(逗号),[](下标) |
不可重载运算符:
成员访问运算符 | . |
---|---|
成员指针范文运算符 | .*,->* |
域运算符 | :: |
长度运算符 | sizeof |
条件运算符 | ?: |
预处理符号 | # |