LINUX.ORG.RU

Вопрос по С++


0

0

Брацы, а почему у меня получилось вызвать с наружи приватный метод?


class classA
{
public:
virtual void method_1(int i)
{
cout << "classA" << endl;
}
};


class classB: public classA
{
private:
void method_1(int i)
{
cout << "classB" << endl;
}
};


int main(int argc, char *argv[])
{
classA *a = new classB();
a->method_1(1);

return 0;
}


Или еще прикол, почему вот это не работает?


using namespace std;

class classA
{
public:
virtual void method_1(int i)
{
cout << "classA" << endl;
}
};


class classB: public classA
{
public:
void method_1(string str)
{
cout << "classB" << endl;
}
};


int main(int argc, char *argv[])
{

classB b;
b.method_1(10);


return 0;
}

tukan
() автор топика
Ответ на: комментарий от tukan

Какого плана ответ ты ожидаешь ? C++ реализован так как хотят большие и важные дядьки программеры, а не так как хочешь ты и поэтому он не всегда соотвествует твоим ожиданиям.

anonymous
()

хочу тебя разочаровать :) но ты в первом примере вызвал public метод, а не private. А про второй - что значит не работает ?

CKulT
()
Ответ на: комментарий от anonymous

Отлично ;) Куча изменений, хоткеев, extended thumbnails, парсинг по контенту, и т.д. Хотя пока только JPEG либа готова под новый формат :)

CKulT
()
Ответ на: комментарий от CKulT

>> но ты в первом примере вызвал public метод, а не private

classA *a = new classB();

Все таки я создал обект класса classB(), хотя очевидно что проверка делается на стадии компиляции...

>> А про второй - что значит не работает ?

Не видит он method_1(int i), который из classA

tukan
() автор топика
Ответ на: комментарий от tukan

>>Все таки я создал обект класса classB(), хотя очевидно что проверка делается на стадии компиляции...

Ну и что. это называется полиморфизм объектов. Ты из объекта a пытаешся вызвать метод, которого нет в классе classA. Если бы ты сделал наоборот - classB *b = new classA, то так можно.

>>>Не видит он method_1(int i), который из classA

Вроде бы и не должен. Я не уверен, сохраняется ли спсиок парпметров в таблице виртуальных функций, но если это так, то ты переопределил метод method_1, поэтому во втором классе виден только один метод method_1(string).

Если хочешь вызвать, то надо b.classA::method_1(10);

CKulT
()
Ответ на: комментарий от CKulT

>>Ну и что. это называется полиморфизм объектов. Ты из объекта a >>пытаешся вызвать метод, которого нет в классе classA.

Чего то не пойму, как же нету, когда есть, толька он приватный
и он вызывается из наружи... По хорошему не нада разрешать менять область видимости виртуальных обектов.


>> то ты переопределил метод method_1

Как можно переопределить метод другим, с таким же именем, то с другими параметрами, по хорощему это называется перегрузил :-)

tukan
() автор топика
Ответ на: комментарий от tukan

>>Чего то не пойму, как же нету, когда есть, толька он приватный 

По мойму ты чего-то не понимаешь. Область памяти new classB будет расценена как данные облясть памяти объекта класса classA, а не classB.

class classA 
{ 
   public: 
   virtual void method_1(int i) 
   { 
       cout << "classA" << endl; 
   } 
}; 

class classB: public classA 
{ 
  public:
  classB() { z = 0; }

  private: 
  void method_1(int i) 
  { 
    cout << "classB" << endl; 
  } 
  public:
     int z;
}; 

classA *a = new classB(); 
a->z; // ошибка - нет такого атрибута 'z'

>> По хорошему не нада разрешать менять область видимости виртуальных обектов.

Можно, это влияет только на область видимоости, и только.

>>Как можно переопределить метод другим, с таким же именем, то с другими параметрами

Дык виртуальные метдоы должны иметь тот же список параметров, что и в родительском классе. В твоём случае не так.

CKulT
()
Ответ на: комментарий от CKulT

#include <stdio.h>

#include <iostream>
#include <string>

using namespace std;

class classA
{
    public:
	classA() {}
	~classA() {}
	
    virtual void m1(int i)
    {
	cout << "classA: " << i << endl;
    }
};

class classB : public classA
{
    public:
	classB() {}
	~classB() {}
	
    virtual void m1(string str)
    {
	cout << "classB: " << endl;
    }
};

int main(int argc, char **argv)
{
    classA *a = new classB;
    
    string s("STR");
    
    a->m1(s);
    
    delete a;

    return 0;
}

[ckult@localhost tmp]$ g++ -o 7 7.cc
7.cc: In function `int main(int, char**)':
7.cc:38: error: no matching function for call to `classA::m1(std::string&)'
7.cc:15: error: candidates are: virtual void classA::m1(int)
[ckult@localhost tmp]$

CKulT
()
Ответ на: комментарий от CKulT

>>Область памяти new classB будет расценена как данные облясть памяти >>объекта класса classA, а не classB.

Я ж и говорю, область видимости проверяется толька на этапе компиляции,
на этапе выполнения найти правильный метод который нада вызвать у С++ ума хватает, а вот на область видимости откровенно кладет.
По другому наверное и быть не может...


>>Дык виртуальные метдоы должны иметь тот же список параметров, что и в >>родительском классе. В твоём случае не так.

Так я и не говорю что это должен быть виртуальный метод, он должен быть
как метод с другим именем, все методы наследуемого класса видны в наследнике, а вот если имя совпало(с методом, который определен в наследнике), а параметры нет, то этот метод не попадает в наследник чего то, нада танцы с бубном, или это не просто так?


tukan
() автор топика
Ответ на: комментарий от CKulT

Нее, не так,

сделай

classB object;
и попробуй

int i = 0;
object.m1(i);

Почему void m1(int i) не попадает в classB из classA?

tukan
() автор топика
Ответ на: комментарий от tukan

>>>Я ж и говорю, область видимости проверяется толька на этапе компиляции, на этапе выполнения найти правильный метод который нада вызвать у С++ ума хватает, а вот на область видимости откровенно кладет. По другому наверное и быть не может...

Неверно! ещё раз повторяю

claasA *a = new classB;

означает почти тоже самое, что

claasA *a = new classA;

Ну понял наконец ? :)

CKulT
()

О, как все запущено...

anonymous
()

1. твоя программа -- типичный пример из любой книги по С++, и там все подробно описано 2. у тебя в классе classB нет функции method_1(int), т.к. виртуальные функции не наследуются.

anonymous
()
Ответ на: комментарий от CKulT

Единственное что я понял, так это то, что если есть выражение classA *a = new ClassB();

то в С++ область видимости определяется тем, чему был присвоен результат, то есть, была рыба, а потом работать будем с ней так же, как и с селедкой, если спросим имя, то получим правильно имя, а захотим еще раз сделать из седедки селедку - нет проблем :-) А вот жабе все определяется как раз new ClassB(), и такого маразма не будет(опять таки, нада проверить)

tukan
() автор топика
Ответ на: комментарий от anonymous

>>у тебя в классе classB нет функции method_1(int), т.к. виртуальные >>функции не наследуются.

Смелое заявление, виртуальные функции не наследуются...

class A{ public: virtual void method_1(); };

class B: public B { public: virtual void method_2(); }

И что, скаэеш в В нету virtual void method_1()?

tukan
() автор топика
Ответ на: комментарий от anonymous

да, это ты загнул про не наследуются - ведь в этом собственно и их смысл (в наследовании)

CKulT
()
Ответ на: комментарий от gpg

Поработай с буржуями, потом посмотрим что ты будеш знать :-)

tukan
() автор топика
Ответ на: комментарий от tukan

Хорошо такой пример:
class A{ public: virtual void method(); };
class B{ public: virtual void method(); };
class D:public A, D {};

...

D d;
B *b=&d;
b->method(); //B::method();

A *a=&d:
a->method(); //A::method();

d.method(); //??????????

Насколько я понимаю класс не наследует виртуальную функцию,
а наследует указатель на таблицу виртуальных функций (в данном
случае их будет 2). А какая функция будет вызвана определяется во время выполнения.
В твоем случае надо так:

int main(int argc, char *argv[])
{
classB b;
((classA)b).method_1(10);

return 0;
}

anonymous
()
Ответ на: комментарий от anonymous

В мандряке есть со времён 9,1 (или раньше ?). Называется вроде URW Gothic.

CKulT
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.