Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » C/C++ - [решено] C++: Подскажите, в чем заключается ошибка.

Ответить
Настройки темы
C/C++ - [решено] C++: Подскажите, в чем заключается ошибка.

Аватара для Oleg_SK

Ветеран


Сообщения: 1328
Благодарности: 144


Конфигурация

Профиль | Отправить PM | Цитировать


Изменения
Автор: Drongo
Дата: 07-12-2009
Описание: тег [code]...[/code] - значок - # на панели задач
Решил изучить C++. Сейчас разбираюсь с наследованием классов и виртуальными функциями. Слабал простенькую программку:
Код: Выделить весь код
//---------------------------------------------------------------------------

#pragma hdrstop
#include <iostream.h>

class Mammal
{
	public:
		Mammal(){cout << "***\n\n";}
		virtual ~Mammal(){}
		virtual void Speak() const {cout << "Mammal speak!\n\n";}

	//protected:
	int z;
};

class Dog : public Mammal
{
	Dog(){}
	virtual ~Dog(){}
	void Speak() const {cout << "Dog speak!\n\n";}
};

class Cat : public Mammal
{
	Cat(){}
	virtual ~Cat(){}
	void Speak() const {cout << "Cat speak!\n\n";}
};
//---------------------------------------------------------------------------

#pragma argsused
int main(int argc, char* argv[])
{
	Mammal * theArray[3];
	Mammal * ptr;
	int choice, i;
	for (i = 0; i < 3; i++) {
		cout << "(1)Dog (2)Cat: ";
		cin >> choice;
		switch (choice)
		{
			case 1:
				ptr = new Dog;
				break;

			case 2:
				ptr = new Cat;
				break;

			default:
				ptr = new Mammal;
				break;
		}

		if (ptr != NULL) {
			theArray[i] = ptr;
		}
		else
		{
			cout << "\n\nNULL ptr!!!\n\n";
        }
	}

    cout << "\n\n";
	for (i = 0; i < 3; i++) {
		theArray[i] -> Speak();
	}

	int x;
	cin >> x;
	return 0;
}
//---------------------------------------------------------------------------
Проблема заключается в том, что эта программа не компилируется; компилятор жалуется, что конструкторы классов Dog и Cat недоступны (is not accessible). Если закомментировать эти конструкторы, то прога нормально компилится и работает... Хотелось бы узнать: из-за чего возникла эта ошибка, и как ее исправить?

-------
Здесь вместо "Спасибо" принято щелкать на "Полезное сообщение" у тех постов, которые вам помогли, или показались полезными.


Отправлено: 02:27, 07-12-2009

 

Аватара для Oleg_SK

Ветеран


Сообщения: 1328
Благодарности: 144

Профиль | Отправить PM | Цитировать


Все, сам разобрался - забыл объявить методы классов Cat и Dog публичными, а по дефолту они являются приватными. Непонятно только почему тогда без проблем вызывался для объектов этих классов метод Speak()? Это связано с его виртуальностью?

-------
Здесь вместо "Спасибо" принято щелкать на "Полезное сообщение" у тех постов, которые вам помогли, или показались полезными.


Отправлено: 02:49, 07-12-2009 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Аватара для Delirium

Ветеран


Сообщения: 5624
Благодарности: 936

Профиль | Отправить PM | Цитировать


Цитата Oleg_SK:
class Mammal
{
public:
Mammal(){cout << "***\n\n";}
virtual ~Mammal(){}
virtual void Speak() const {cout << "Mammal speak!\n\n";} »
Так выше же написано PUBLIC: и идет перечисление публичных функций, в т.ч. и Speak. Потому и видим.

-------

Пройденные курсы:
[Microsoft №10174 Sharepoint], [SharePoint]
Мои проекты:[CheckAdmins], [NetSend7], [System Uptime], [Remote RAdmin LogViewer],[Netdom GDI], [Holidays - напоминалка о днях рождения]

А я офис-гуру :)

Это сообщение посчитали полезным следующие участники:

Отправлено: 03:03, 07-12-2009 | #3


ИО Капитана Очевидности


Contributor


Сообщения: 5387
Благодарности: 1105

Профиль | Отправить PM | Цитировать


Цитата Oleg_SK:
Если закомментировать эти конструкторы, то прога нормально компилится и работает... »
Потому что в этом случае компилятор автоматически создаёт конструкторы, которые являются public.

-------
Самое совершенное оружие, которым забиты арсеналы богатых и процветающих наций, может легко уничтожить необразованного, больного, бедного и голодного. Но оно не может уничтожить невежество, болезнь, нищету и голод. (Фидель Кастро)

Почему всех осужденных за измену Родине при Сталине реабилитировали при Горбачёве по отсутствию состава преступления? Потому что при Горбачёве измену Родине перестали считать преступлением.

Это сообщение посчитали полезным следующие участники:

Отправлено: 03:16, 07-12-2009 | #4


Аватара для Oleg_SK

Ветеран


Сообщения: 1328
Благодарности: 144

Профиль | Отправить PM | Цитировать


Цитата Delirium:
Так выше же написано PUBLIC: и идет перечисление публичных функций, в т.ч. и Speak. Потому и видим. »
Непонятка в том, что без проблем вызываются и те виртуальные функции Speak(), которые определены в классах Dog и Cat, а они, из-за допущенной мной ошибки, были там приватными...

Цитата El Scorpio:
Потому что в этом случае компилятор автоматически создаёт конструкторы, которые являются public. »
То есть конструкторы и деструктор класса нужно всегда объявлять как публичные методы. Я верно понял? В книге, которую я читаю, об этом прямо не упоминается (по крайней мере, я не помню чтобы там шла об этом речь)...

-------
Здесь вместо "Спасибо" принято щелкать на "Полезное сообщение" у тех постов, которые вам помогли, или показались полезными.


Отправлено: 07:17, 07-12-2009 | #5


ИО Капитана Очевидности


Contributor


Сообщения: 5387
Благодарности: 1105

Профиль | Отправить PM | Цитировать


Oleg_SK, не содержащие какого-то специфичного кода методы "деструктор", "конструктор по умолчанию", "конструктор копирования" и "оператор присваивания" в C++ объявлять не обязательно - компилятор их создаёт и заполняет стандартным кодом автоматически.

Цитата Oleg_SK:
То есть конструкторы и деструктор класса нужно всегда объявлять как публичные методы. »
Нет, не всегда.
Порою вышеперечисленные методы специально объявляют, как private, если хотят запретить данное действие в классе и его потомках. Существование "закрытого" метода в родительском классе не позволяет компилятору генерировать стандартный код в производных объектах. Данное действие будет запрещено до явного объявления открытого метода.
Явный пример - класс TObject из Borland C++ Builder. Объекты, производные от данного абстрактного класса, могут располагаться только в "куче", из-за чего операции создания объекта-копии и присваивания одного объекта другому применимы. По-этому для данного объекта явно указаны private методы TObject (const TObject &) и TObject& operator = (const TObject &).
Далее, для объектов класса TComponent - невидимый компонент экранной формы - и производных от него всегда должно быть определено значение поля "владелец" (Owner). В*результате адрес компонента-владельца указывается, как параметр конструктора, а конструктор по умолчанию TComponent (void) также объявлен "закрытым" (или "защищённым", не помню точно)

А вот результат создания "закрытого" деструктора я предсказать не могу

-------
Самое совершенное оружие, которым забиты арсеналы богатых и процветающих наций, может легко уничтожить необразованного, больного, бедного и голодного. Но оно не может уничтожить невежество, болезнь, нищету и голод. (Фидель Кастро)

Почему всех осужденных за измену Родине при Сталине реабилитировали при Горбачёве по отсутствию состава преступления? Потому что при Горбачёве измену Родине перестали считать преступлением.

Это сообщение посчитали полезным следующие участники:

Отправлено: 02:03, 08-12-2009 | #6


Аватара для Oleg_SK

Ветеран


Сообщения: 1328
Благодарности: 144

Профиль | Отправить PM | Цитировать


Кстати, забыл задать еще один вопрос по терминологии: является ли рекурсией ситуация, когда метод одного объекта класса вызывает себя в контексте другого объекта этого же класса?

-------
Здесь вместо "Спасибо" принято щелкать на "Полезное сообщение" у тех постов, которые вам помогли, или показались полезными.


Отправлено: 07:22, 09-12-2009 | #7


Аватара для Delirium

Ветеран


Сообщения: 5624
Благодарности: 936

Профиль | Отправить PM | Цитировать


Самый простой способ ответить на вопрос - поставить точку отладки на начало функции и повызывать метод Если будет сам в себя заходить, то рекурсия.
Википедия - рекурсия

-------

Пройденные курсы:
[Microsoft №10174 Sharepoint], [SharePoint]
Мои проекты:[CheckAdmins], [NetSend7], [System Uptime], [Remote RAdmin LogViewer],[Netdom GDI], [Holidays - напоминалка о днях рождения]

А я офис-гуру :)


Отправлено: 07:35, 09-12-2009 | #8


Аватара для Oleg_SK

Ветеран


Сообщения: 1328
Благодарности: 144

Профиль | Отправить PM | Цитировать


Вызывать то она себя вызывает. Если бы речь шла об обычной функции, то и вопроса бы не возникло, т.к. это очевидная рекурсия. У меня с этим объектно-ориентированным программированием уже похоже скоро крышу сорвет, т.к. начал сомневаться в обычных вещах. Если не углубляться в реализацию классов, то может создаться впечатление что у каждого объекта класса имеется своя копия набора методов этого класса. Например, есть связанный список, узлами которого являются объекты одного класса. У каждого объекта этого класса есть метод Insert, который, проверив вставляемый в список узел, решает либо самостоятельно вставить этот узел, либо отправляет его дальше по списку, передавая его методу Insert следующего узла списка (так производится сортировка при вставке). В списке есть множество узлов и соответственно множество идентичных по коду методов. Таким образом создается впечатление, что лично себя метод Insert не вызывает, а вызывает свою копию в следующем узле списка, которая в свою очередь может вызвать очередную свою копию в следующем узле списка и т.д. Рекурсия - это ситуация, когда функция вызывает саму себя. В описанном же мной случае, создается впечатление, что есть множество копий одной функции, которые последовательно вызывают друг-друга... Поэтому и возник вопрос: а рекурсия ли это вообще (если не углубляться в реализацию классов компилятором)?

-------
Здесь вместо "Спасибо" принято щелкать на "Полезное сообщение" у тех постов, которые вам помогли, или показались полезными.


Отправлено: 08:39, 09-12-2009 | #9


ИО Капитана Очевидности


Contributor


Сообщения: 5387
Благодарности: 1105

Профиль | Отправить PM | Цитировать


Цитата Oleg_SK:
Если не углубляться в реализацию классов, то может создаться впечатление что у каждого объекта класса имеется своя копия набора методов этого класса. »
Цитата Oleg_SK:
В списке есть множество узлов и соответственно множество идентичных по коду методов. Таким образом создается впечатление, что лично себя метод Insert не вызывает, а вызывает свою копию в следующем узле списка, которая в свою очередь может вызвать очередную свою копию в следующем узле списка и т.д. »
Обычный "метод класса" - это обычная функция, которая содержит неявный параметр this (указатель на самого себя). Данный указатель используется для обращения к полям объекта и подставляется в вызовы других методов этого же объекта. А "статичный метод" (static) - это функция без параметра this. Как следствие, из неё можно обращаться только к статичным полям (которые общие для всех объектов данного класса) и вызывать другие статичные методы.

Как следствие, в рассматриваемой ситуации имеем N вложенных (рекурсивных) вызовов функции с разными значениями параметра this

-------
Самое совершенное оружие, которым забиты арсеналы богатых и процветающих наций, может легко уничтожить необразованного, больного, бедного и голодного. Но оно не может уничтожить невежество, болезнь, нищету и голод. (Фидель Кастро)

Почему всех осужденных за измену Родине при Сталине реабилитировали при Горбачёве по отсутствию состава преступления? Потому что при Горбачёве измену Родине перестали считать преступлением.

Это сообщение посчитали полезным следующие участники:

Отправлено: 02:37, 10-12-2009 | #10



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » C/C++ - [решено] C++: Подскажите, в чем заключается ошибка.

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
[решено] Ошибка ДНС 6702. В чем может быть дело? tlekkanapin Microsoft Windows NT/2000/2003 6 30-06-2010 16:11
[решено] Подскажите чем оформить EXE-шник Str_ani_ck AutoIt 16 05-08-2009 16:15
[решено] Подскажите в чем проблемма. misha5539 Непонятные проблемы с Железом 9 13-04-2008 14:51
FreeBSD - [решено] Ошибка при установке xorg, подскажите куда копать? masus Общий по FreeBSD 7 26-10-2007 15:48
Проблема с HDD или Виндой? И в чем она заключается? Virus1981 Непонятные проблемы с Железом 15 09-07-2006 14:01




 
Переход