多继承的概念和优缺点

解析:
       实际生活中,一些事物往往会拥有两个或两个以上事物的属性,为了解决这个问题,C++引入了多重继承的概念,C++允许为一个派生类指定多个基类,这样的继承结构被称做多重继承。举个例子:
       人(Person)可以派生出作家(Author)和程序员(Programmer),然而程序员作者同时拥有作家和程序员的两个属性,即既能编程又能写作,如下图所示。 


使用多重继承的例子程序如下:
       #include <iostream>
       using namespace std;
    
       class Person
       {
      public:
                void sleep() {cout << "sleep" << endl;}
                void eat() {cout << "eat" << endl;}
       };
    
     class Author : public Person            //Author继承自Person
     {
     public:
              void writeBook() {cout << "write Book" << endl;}
     };
    
     class Programmer : public Person      //Programmer继承自Person
     {
     public:
              void writeCode() {cout << "write Code" << endl;}
     };
    
     class Programmer_Author : public Programmer, public Author    //多重继承
     {
     };
    
     int main()
     {
              Programmer_Author pa;
    
              pa.writeBook();   //调用基类Author的方法
              pa.writeCode();   //调用基类Programmer的方法
              pa.eat();         //编译错误,eat()定义不明确
              pa.sleep();       //编译错误,sleep()定义不明确
    
              return 0;
     }

       多重继承的优点很明显,就是对象可以调用多个基类中的接口,如代码31行与代码32行对象pa分别调用Author类的writeBook()函数和Programmer类的writeCode()函数。
       多重继承的缺点是什么呢?如果派生类所继承的多个基类有相同的基类,而派生类对象需要调用这个祖先类的接口方法,就会容易出现二义性。代码33、34行就是因为这个原因而出现编译错误的。因为通过多重继承的Programmer_Author类拥有Author类和Programmer类的一份拷贝,而Author类和Programmer类都分别拥有Person类的一份拷贝,所以Programmer_Author类拥有Person类的两份拷贝,在调用Person类的接口时,编译器会不清楚需要调用哪一份拷贝,从而产生错误。对于这个问题通常有两个解决方案:
(1)加上全局符确定调用哪一份拷贝。比如pa.Author::eat()调用属于Author的拷贝。
(2)使用虚拟继承,使得多重继承类Programmer_Author只拥有Person类的一份拷贝。比如在11行和17行的继承语句中加入virtual就可以了。
      

 class Author : virtual public Person         //Author虚拟继承自Person
       class Programmer : virtual public Person    //Programmer虚拟继承自Person


多重继承的概念和优缺点?
答案:

实际生活中,一些事物往往会拥有两个或两个以上事物的属性,为了解决这个问题,C++引入了多重继承的概念。
多重继承的优点是对象可以调用多个基类中的接口。
多重继承的缺点是容易出现继承向上的二义性。

 

原文:http://blog.sina.com.cn/s/blog_5396eb530100mtc9.html

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单HTML 贪吃蛇代码示例: ```html <!DOCTYPE html> <html> <head> <title>贪吃蛇</title> <style> #game-board { width: 400px; height: 400px; border: 1px solid black; position: relative; } .snake { width: 10px; height: 10px; background-color: green; position: absolute; } .food { width: 10px; height: 10px; background-color: red; position: absolute; } </style> </head> <body> <div id="game-board"></div> <script> // 游戏设置 const boardSize = 400; // 游戏面板大小 const unitSize = 10; // 每个单元格的大小 // 创建贪吃蛇和食物 let snake = [{x: 0, y: 0}]; let food = {x: 0, y: 0}; let direction = 'right'; // 随机生成食物位置 function generateFood() { food.x = Math.floor(Math.random() * (boardSize / unitSize)) * unitSize; food.y = Math.floor(Math.random() * (boardSize / unitSize)) * unitSize; } // 更新贪吃蛇位置 function updateSnake() { // 移动蛇的身体 for (let i = snake.length - 1; i > 0; i--) { snake[i].x = snake[i - 1].x; snake[i].y = snake[i - 1].y; } // 移动蛇的头部 if (direction === 'right') { snake[0].x += unitSize; } else if (direction === 'left') { snake[0].x -= unitSize; } else if (direction === 'up') { snake[0].y -= unitSize; } else if (direction === 'down') { snake[0].y += unitSize; } } // 检查是否吃到食物 function checkFood() { if (snake[0].x === food.x && snake[0].y === food.y) { snake.push({x: snake[snake.length - 1].x, y: snake[snake.length - 1].y}); generateFood(); } } // 检查是否碰到边界或自己的身体 function checkCollision() { if (snake[0].x < 0 || snake[0].x >= boardSize || snake[0].y < 0 || snake[0].y >= boardSize) { clearInterval(gameInterval); alert('游戏结束!'); location.reload(); } for (let i = 1; i < snake.length; i++) { if (snake[0].x === snake[i].x && snake[0].y === snake[i].y) { clearInterval(gameInterval); alert('游戏结束!'); location.reload(); } } } // 渲染贪吃蛇和食物 function render() { // 清空游戏面板 document.getElementById('game-board').innerHTML = ''; // 渲染食物 let foodElement = document.createElement('div'); foodElement.className = 'food'; foodElement.style.left = food.x + 'px'; foodElement.style.top = food.y + 'px'; document.getElementById('game-board').appendChild(foodElement); // 渲染贪吃蛇 for (let i = 0; i < snake.length; i++) { let snakeElement = document.createElement('div'); snakeElement.className = 'snake'; snakeElement.style.left = snake[i].x + 'px'; snakeElement.style.top = snake[i].y + 'px'; document.getElementById('game-board').appendChild(snakeElement); } } // 处理键盘事件 document.addEventListener('keydown', function(event) { if (event.code === 'ArrowRight' && direction !== 'left') { direction = 'right'; } else if (event.code === 'ArrowLeft' && direction !== 'right') { direction = 'left'; } else if (event.code === 'ArrowUp' && direction !== 'down') { direction = 'up'; } else if (event.code === 'ArrowDown' && direction !== 'up') { direction = 'down'; } }); // 主循环 let gameInterval = setInterval(function() { updateSnake(); checkFood(); checkCollision(); render(); }, 100); // 初始化游戏 generateFood(); render(); </script> </body> </html> ``` 注释已经得比较详细了,这里简单介绍一下代码的实现逻辑: - 首先定义了游戏面板大小、单元格大小、贪吃蛇、食物和当前方向等变量; - 在 `generateFood()` 函数中随机生成食物位置; - 在 `updateSnake()` 函数中更新贪吃蛇位置; - 在 `checkFood()` 函数中检查是否吃到食物; - 在 `checkCollision()` 函数中检查是否碰到边界或自己的身体; - 在 `render()` 函数中渲染贪吃蛇和食物; - 在 `document.addEventListener()` 中处理键盘事件,改变当前方向; - 在主循环中不断调用上述函数,并每隔一段时间重新渲染游戏面板; - 最后在页面加载完成后初始化游戏,生成食物并渲染游戏面板。 这只是一个非常简单的示例,实际上还有很多方面可以优化和改进,比如添加计分系统、增加难度等等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值