C, PHP, VB, .NET

Дневникът на Филип Петров


* Виртуални класове

Публикувано на 14 ноември 2008 в раздел С/С++.

При директното наследяване на множество базови класове е възможно един производен клас да наследи многократно даден базов клас. Така обаче може да се получи дублиране на член променливи.

Нека например класа vehicle има два производни класа: motorvehicle (добавя допълнителна информация за типа двигател на превозното срество) и passengervehicle (добавя информация за максималния брой пътници в превозното средство). Ако създадем клас car, който наследява едновременно motorvehicle и passengervehicle, то ние ще получим дублиране на член-променливи, тъй като класа car ще наследи двукратно член-променливите декларирани в класа vehicle.

Многократното наследяване може да се избегне чрез наследяване на базовия клас като виртуален. Това предотвратява присъствието на 2(или повече) копия на базовия клас във всеки следващ индиректен производен клас. Декларацията в този случай ще има вида:

	class vehicle { ... };
	class motorvehicle : virtual public vehicle { ... };
	class passengervehicle : virtual public vehicle { ... };
	class car : public motorized, public road_use { ... };

Ето как ще изглежда примерната програма:

	#include "stdafx.h"
	#include "iostream.h"

	class vehicle {
		int num_wheels;
		int weight;
		public:
		vehicle(int w, int r)
		{
			num_wheels = w; weight = r;
		}
		void showv(){
			cout << "Wheels:" << num_wheels << endl;
			cout << "Weight:" << weight << endl;
		}
	};

	enum motor {gas, electric, diesel};

	class motorvehicle : virtual public vehicle {
		enum motor mtr;
		public:
		motorvehicle(enum motor m, int w, int r) : vehicle(w, r) {
			mtr = m;
		}

		void showm() {
			cout << "Motor: ";
			switch(mtr) {
				case gas : cout << "Gas";
					break;
				case electric : cout << "Electric";
					break;
				case diesel : cout << "Diesel";
					break;
			}
			cout << endl;
		}
	};

	class passangervehicle : virtual public vehicle {
		int passengers;
		public:
		passangervehicle(int p, int w, int r) : vehicle(w, r){
			passengers = p;
		}

		void showp() {
			cout << "Passengers:" << passengers << '\n';
		}
	};

	enum steering {power, rack_pinion, manual};

	class car : public motorvehicle, public passangervehicle {
		enum steering strng;
		public:
		car(enum steering s, enum motor m, int p, int w, int r) :
			motorvehicle(m, w, r), passangervehicle(p, w, r), vehicle(w, r)
		{
			strng = s;
		}

		void show() {
			showv();
			showp();
			showm();
			cout << "Steering: ";
			switch(strng) {
				case power : cout << "Power";
					break;
				case rack_pinion : cout << "Rack and pinion";
					break;
				case manual : cout << "Manual";
					break;
			}
			cout << endl;
		}
	};

	int main() {
		car c(power, gas, 5, 4, 1200);
		c.show();
		return 0;
	}

Задача: Към горният пример добавете клас „truck“, който е производен само на класа „motorvehicle“ и добавя като функционалност член променлива load (максимален товар) и функция, която го отпечатва на екрана.

 



2 коментара


  1. нетаксуван каза:

    Здравейте. Виждам, че статията е 4-годишна, и предполагам, че с достатъчно ровене бих намерил отговора на въпроса си, но тъй като имам своите причини да ме мързи страшно в момента, бихте ли бил така добър да отговорите на следното: какво губим при наследяване на клас като виртуален? Разбрах, че спестяваме разхищение на памет (освен неразборията от еднаквите имена), та сигурно това е правият път в подобни ситуации. Но има ли някакво отражение върху производителността например?

  2. Не смятам, че има разхищение на ресурси.

Добави коментар

Адресът на електронната поща няма да се публикува


*