C实现C++的面向对象特性

面向对象的程序设计有三大特性:封装、继承和多态。

1 封装

  • C++语言中支持数据封装,类是支持数据封装的工具,对象是数据封装的实现。在封装中,还提供一种对数据访问的控制机制,使得一些数据被隐藏在封装体内,因此具有隐藏性。封装体与外界进行信息交换是通过操作接口进行的。
  • 封装性实际上是由编译器去识别关键字public、private和protected来实现的,体现在类的成员可以有公有成员(public),私有成员(private),保护成员(protected)。
  • 私有成员是在封装体内被隐藏的部分,只有类体内说明的函数(类的成员函数)才可以访问私有成员,而在类体外的函数时不能访问的,公有成员是封装体与外界的一个接口,类体外的函数可以访问公有成员,保护成员是只有该类的成员函数和该类的派生类才可以访问的。
  • 类是一种复杂的数据类型它是将不同类型的数据和与这些数据相关的操作封装在一起的集合体。因此,类具有对数据的抽象性,隐藏性和封装性
  • 封装性的目的是为了增加代码健壮性,减少写代码时出错的概率。也就是说只要能编译通过,在C++的类中无论是public、protected还是private,最终生成的汇编代码其实是一致的。

而继承和多态是C++对C语言的补充,使得代码写起来更加简单。

2 继承

  • C++语言允许单继承和多继承。继承是面向对象语言的重要特性,是实现抽象和共享的一种机制。
  • C++语言中的继承机制可以克服传统的面向过程程序设计的缺点,因为传统编程方式不能重复使用程序而造成资源的浪费,而c++语言提供了无限重复利用程序资源的一种新途径。
  • 一个类可以根据需要生成它的派生类,派生类还可以再生成派生类。派生类继承基类的成员,另外,还可以定义自己的成员。
  • C++中的继承有两个方面的意思,第一子类拥有父类所有的成员变量,第二子类也拥有父类的所有成员函数,所以很多C++教材会说一句话,子类拥有父类的所有特性。

3 多态

  • 多态性是指对不同类的对象发出相同的消息将会有不同的实现。多态性也可以理解为,在一般类中定义的属性或服务被特殊类继承后,可以具有不同的数据类型或不同的实现。可见,多态性与继承性相关联。简单的说,多态性是指发出同样的消息被不同的数据类型的对象接收后导致不同的行为。
  • C++语言支持多态性表现在:
    1. C++语言允许函数重载和运算符重载
    2. C++语言通过定义虚函数来支持动态联编,动态联编是多态性的一个重要的特征。
  • 多态特性的工作依赖虚函数的定义,在需要解决多态问题的重载成员函数前,加上virtual关键字,那么该成员函数就变成了虚函数,从上例代码运行的结果看,系统成功的分辨出了对象的真实类型,成功的调用了各自的重载成员函数。如果在基类某些函数前面声明为virtual,则C++编译器会在内存对象模型前面插入一个虚函数指针,该指针指向一个虚函数表,正是因为我们可以改变虚函数指针所指函数表地址,从而实现其多态操作。
  • 多态特性让程序员省去了细节的考虑,提高了开发效率,使代码大大的简化,当然虚函数的定义也是有缺陷的,因为多态特性增加了一些数据存储和执行指令的开销,所以能不用多态最好不用。

C语言实现封装性

属性方法(一般定义为函数指针)封装到特定结构体中。

怎样定义函数指针?

#include <iostream>
#include <vector>
#include <ctime>
#include <cstdlib>
using namespace std;

// 定义函数
int add(int x, int y)
{
    return x+y;
}

// 定义函数指针
//函数指针,指针变量的名字是padd
int(*padd)(int , int ) = add;

// 用typedef重命名
typedef int(*PADD)(int , int ); //注意typedef后要加分好,#define宏定义后没有分号
PADD padd2 = add;


int main(void)
{
	cout << padd(1, 2) << endl;
	cout << padd2(3, 4) << endl;

	return 0;	
}

结果

这里初始化函数指针的时候就得赋值。

C语言实现继承性

C++中类的成员变量的继承其实就相当于是C语言的结构体嵌套,而在写代码的时候可以省略其中父类的嵌套。也可以在一个结构体里面定义另一个结构体的指针。

C语言实现多态性

首先是C++实现多态

#include <iostream>
#include <vector>
#include <ctime>
#include <cstdlib>
using namespace std;


// C++中的继承与多态
struct A
{
    virtual void fun()    // C++中的多态:通过虚函数实现
    {
        cout<<"A:fun()"<<endl;
    }

    int a;
};
struct B:public A         // C++中的继承:B类公有继承A类
{
    virtual void fun()    // C++中的多态:通过虚函数实现(子类的关键字virtual可加可不加)
    {
        cout<<"B:fun()"<<endl;
    }

    int b;
};

void test2()
{
	A a;            // 父类对象
	B b;            // 子类对象
	
	A* pA = &a;     // 父类指针指向父类对象
	pA->fun();
	
	pA = &b;        // 父类指针指向父类对象,多态
	pA->fun();
}



int main(void)
{
	test2();

	return 0;	
}

结果

然后是C语言实现多态

#include <iostream>
#include <vector>
#include <ctime>
#include <cstdlib>
using namespace std;

// 重定义一个指针类型
typedef void (*pf)();

// 父类
typedef struct _A
{
	pf _f;	
}A;

// 子类
typedef struct _B
{
	A _b;		// 在子类中定义一个基类的对象即可实现对父类的继承。 
}B;

void FuncA()
{
	printf("%s\n","Base A::fun()");
}

void FuncB() 
{
    printf("%s\n","Derived B::fun()");
}

void test2()
{
	A a;		// 父类对象 
	B b; 		// 子类对象
	
	a._f = FuncA;		// 类的对象调用父类的同名函数
	b._b._f = FuncB;	// 子类的对象调用子类的同名函数
	
	A* pa = &a;			// 定义一个父类指针指向父类的对象
	pa->_f();			// 调用父类的同名函数
	pa = (A*)(&b);		// 让父类指针指向子类的对象,由于类型不匹配所以要进行强转
	pa->_f(); 			// 调用子类的同名函数
}

int main(void)
{
	test2();

	return 0;	
}

结果

转载:C语言实现C++的三大特性(封装、继承和多态)_如何用c 实现 c++ 的面向对象特性(封装、继承、多态)-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 C 语言中,没有原生的面向对象特性,但可以通过结构体和函数指针等方式来实现类似于面向对象的编程。以下是一个简单的五子棋游戏的实现,其中包含了棋盘、棋子和玩家等相关结构体,以及对应的函数指针实现的方法。 ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define BOARD_SIZE 15 #define MAX_NAME_LENGTH 50 typedef struct { int x; int y; } Point; typedef struct { char name[MAX_NAME_LENGTH]; char chess; } Player; typedef struct { char board[BOARD_SIZE][BOARD_SIZE]; Player *players[2]; int current_player; void (*print_board)(char board[BOARD_SIZE][BOARD_SIZE]); void (*place_chess)(char board[BOARD_SIZE][BOARD_SIZE], Point point, char chess); int (*check_win)(char board[BOARD_SIZE][BOARD_SIZE], Point point); Point (*get_input)(void); } Game; void print_board(char board[BOARD_SIZE][BOARD_SIZE]) { printf(" "); for (int i = 0; i < BOARD_SIZE; i++) { printf("%c ", i + 'A'); } printf("\n"); for (int i = 0; i < BOARD_SIZE; i++) { printf("%2d", i + 1); for (int j = 0; j < BOARD_SIZE; j++) { printf("%c ", board[i][j]); } printf("\n"); } } void place_chess(char board[BOARD_SIZE][BOARD_SIZE], Point point, char chess) { board[point.x][point.y] = chess; } int check_win(char board[BOARD_SIZE][BOARD_SIZE], Point point) { char chess = board[point.x][point.y]; // check horizontal int count = 1; for (int i = point.y - 1; i >= 0; i--) { if (board[point.x][i] == chess) { count++; } else { break; } } for (int i = point.y + 1; i < BOARD_SIZE; i++) { if (board[point.x][i] == chess) { count++; } else { break; } } if (count >= 5) return 1; // check vertical count = 1; for (int i = point.x - 1; i >= 0; i--) { if (board[i][point.y] == chess) { count++; } else { break; } } for (int i = point.x + 1; i < BOARD_SIZE; i++) { if (board[i][point.y] == chess) { count++; } else { break; } } if (count >= 5) return 1; // check diagonal count = 1; for (int i = point.x - 1, j = point.y - 1; i >= 0 && j >= 0; i--, j--) { if (board[i][j] == chess) { count++; } else { break; } } for (int i = point.x + 1, j = point.y + 1; i < BOARD_SIZE && j < BOARD_SIZE; i++, j++) { if (board[i][j] == chess) { count++; } else { break; } } if (count >= 5) return 1; // check anti-diagonal count = 1; for (int i = point.x - 1, j = point.y + 1; i >= 0 && j < BOARD_SIZE; i--, j++) { if (board[i][j] == chess) { count++; } else { break; } } for (int i = point.x + 1, j = point.y - 1; i < BOARD_SIZE && j >= 0; i++, j--) { if (board[i][j] == chess) { count++; } else { break; } } if (count >= 5) return 1; return 0; } Point get_input(void) { char input[MAX_NAME_LENGTH]; printf("Please input the position (e.g. \"A1\"): "); scanf("%s", input); Point point; point.x = input[1] - '1'; point.y = input[0] - 'A'; return point; } void play_game(Game *game) { while (1) { Player *player = game->players[game->current_player]; printf("%s's turn (%c)\n", player->name, player->chess); Point point = game->get_input(); if (game->board[point.x][point.y] != ' ') { printf("This position has been occupied, please choose another one.\n"); continue; } game->place_chess(game->board, point, player->chess); game->print_board(game->board); if (game->check_win(game->board, point)) { printf("%s wins!\n", player->name); break; } game->current_player = 1 - game->current_player; } } int main() { Game game; game.current_player = 0; game.print_board = print_board; game.place_chess = place_chess; game.check_win = check_win; game.get_input = get_input; Player player1 = {"Player 1", 'X'}; Player player2 = {"Player 2", 'O'}; game.players[0] = &player1; game.players[1] = &player2; memset(game.board, ' ', sizeof(game.board)); game.print_board(game.board); play_game(&game); return 0; } ``` 在上述代码中,我们定义了 `Point`、`Player` 和 `Game` 三个结构体,分别表示一个点的坐标、一个玩家和一个游戏。`Game` 结构体中包含了棋盘、两个玩家、当前玩家、打印棋盘、落子、胜利判断和获取输入等函数指针。通过这些函数指针,我们可以方便地实现不同的游戏逻辑。 在 `play_game` 函数中,我们通过循环来进行游戏,每次轮到一个玩家时,获取输入、落子、打印棋盘、判断胜利并切换到下一个玩家。如果有一方胜利,则结束游戏。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值