C, PHP, VB, .NET

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


* Наследяване

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

Когато един клас наследява друг се използва общата форма:

	class <производен-клас>:<тип-достъп> <име-базов-клас> {
		//...
	};

Типът достъп е една от трите ключови думи: public, private или protected. Разликата между тях е:
– Ако наследяването е тип public, то на производния клас се допуска достъп до членовете на неговия собствен клас, на неговия базов клас и на функции, външни за класовете.
– Ако наследяването е тип protected, то се допуска достъп до членовете на неговия собствен клас, на неговия базов клас, но не се допуска достъп на функции външни за класа.
– Ако наследяването е тип private, то производният клас няма достъп до private елементите на базовия клас и външни функции.

Ако е необходимо да се предаде аргумент на конструктора на базовия клас, то всички необходими аргументи за базовия и за производния клас се предават на конструктора на производния клас. Като се използва разширената форма на декларация на конструктора на производния клас, могат да се предадат съответните аргументи и към базовия клас:

	<производен конструктор>(списък аргументи):<базов-клас>(списък аргументи) {
		//тяло на конструктора на производния клас
	}

Пример: Дефинираме базов клас vehicle и два производни класа – car и truck:

	#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: ";
			cout << num_wheels;
			cout << endl;
			cout << "Weight: ";
			cout << weight;
			cout << endl;
		}
	};

	// Клас кола наследява клас превозно средство
	class car : public vehicle {
		// Добавя се нова променлива
		int passengers;

		public:
		// Конструктора се предефинира, така че
		// да приема три аргумента. Два от тях се
		// предават като аргументи на конструктора
		// на базовия клас
		car(int p, int w, int r) : vehicle(w, r)
		{
			passengers = p;
		}

		// В нова функция show извикваме вече
		// съществуващата в базовия клас функция
		// showv и добавяме функционалност
		void show()
		{
			showv();
			cout << "Passengers: ";
			cout << passengers;
			cout << endl;
		}
	};

	// Аналогично създаваме втори производен клас
	class truck : public vehicle {
		int loadlimit;

		public:

		truck(int l, int w, int r) : vehicle(w, r)
		{
			loadlimit = l;
		}

		void show(){
			showv();
			cout << "Loadlimit: ";
			cout << loadlimit;
			cout << endl;
		}
	};

	int main()
	{
		car c(5, 4, 1200);
		truck t(30000, 12, 3000);
		cout << "Car: " << endl;
		c.show();
		cout << endl << "Truck " << endl;
	 	t.show();
		return 0;
	}

Задача: Съставете базов клас триъгълник с четири елемента дължина на съответните страни и конструктори, който инициализират и валидират входните данни. Направете функция на базовия клас за намиране на лицето на триъгълника по хереоновата хормула. Създайте:
– Производен клас „равнобедрен триъгълник“ и предефинирайте конструктора.
– Производен клас „равностранен триъгълник“ и предефинирайте конструктора. Напишете втора функция за изчисляване на лицето на триъгълник, която използва директно формулата за лице на равностранен триъгълник: a*a*sqrt(3)/4.

 



8 коментара


  1. p0 каза:

    Интересно…опитах примерът 1:1, който е за колата и камиона и в полето за loadlimit ми излезе „-858993460“, а всичко изглежда вярно. Имате ли представа от какво би могла да се получи такава грешка?

  2. Ако ти излиза това число, то най-вероятно променливата НЕ е инициализирана (няма присвоена стойност). В случая ти се извежда стойността по подразбиране.

    Тази променлива „loadlimit“ я има само и единствено в клас „truck“ и се инициализира от конструктора му:
    truck(int l, int w, int r) : vehicle(w, r) {
    loadlimit = l;
    }

    Щом ти се показва тази стойност, значи просто тази инициализация НЕ е станала правилно.

    Вариант 1 – имаш променлива loadlimit на още едно място и става объркване коя от двете да се инициализира. Ето например как може да стане това:
    truck(int l, int w, int r) : vehicle(w, r) {
    int loadlimit = l; // ГРЕШКА!!!
    }

    Вариант 2 – класа не се инициализира правилно в main метода (предава се невалидна стойност, например null)…

    Ако намериш грешката моля пиши…

  3. p0 каза:

    Аз в main бях инициализирала променливата по същия начин както Вас тук в примера. Създадох обект от типа на класа truck – t(30000,12,3000). Вероятно се е получило някакво дублиране тогава, или компилаторът се е бъгнал, защото сега излезе коректна стойност за loadlimit. Иначе в класа truck си я бях декларирала в private, а в констуктора само я инициализирах и така. Благодаря.

  4. Leni каза:

    Имам един въпрос като ситуацията е следна :ако имаме базов клас студент и клас наследник успех със съответните член-данни и член функции как ще се осъществи търсене на студент по зададен факултетен номер?

  5. Не може да имаш базов клас „Студент“ и наследник „Оценки“. Можеш да имаш базов клас „Студент“ и наследник „СТУДЕНТ с оценки“.

    Наследникът взима характеристиките (името, факултетния номер, т.н.) на базовия клас.

  6. Leni каза:

    в масив от обекти на класа наследник

  7. Ivo каза:

    Еми аз какво да кажа, като имам базов клас библиотека и наследник книга? Страшно тъпи условия са зададени. Не знам защо го пиша тук, след като Вие не ни водите по предмета ама все пак да си кажа мнението. Ще си променя условието, така че да има смисъл и няма да правя никакви наследявания. Дано Станков не се сърди.

  8. Ivo – не мога да взема отношение. Случват се и технически грешки. Вярвам, че асистента ще коригира условие на задача, ако е очевидно грешно.

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

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


*