воскресенье, 20 июля 2008 г.

Неоднозначности в базовых классах

Известно, что в языке C++ допускается использование функции с одинаковыми именами, но разными объявлениями параметров. Это называется перегрузкой функции. Нельзя перегружать функции, отличающиеся лишь типом возвращаемого значения.

Итак, пример!
#include <iostream>
void foo();
void foo(int);

void main()
{
foo(7);
foo();
}

void foo()
{
std::cout << "We are in foo()";
}

void foo(int a)
{
std::cout << "We are in foo(int)";
}
В данном случае компилятор без труда определит, какую версию перегруженной функции надо вызвать Теперь обратимся к классам. Пример:
class B1
{
public:
void g(int) { }
};

class B2
{
public:
void g() { }
};

class: public B1, public B2
{
public:
int i;
};

void main()
{
D dobj;
D *dptr = &dobj;
dptr->g();
dptr->g(3);
}
Эта программа некорретна. Компилятор выдаст нам ошибку, ссылаясь на неоднозначность функции g(). Но почему? В классе B1 имеем g(int), в классе B2 имеем g(), класс D наследует B1 и B2, в итоге должны иметь в классе D перегруженную функцию с двумя версиями. Они различаются параметрами, согласно правилу перегрузки, все должно быть гладко, но... тем не менеее ошибка! А дело тут в компиляторе, как уже все догадались. из-за того, что проверка на наличие неоднозначностей происходит во время компиляции, т.е. перед проверками контроля доступа и типов. Поэтому неоднозначность может быть даже тогда, когда один из нескольких членов с одним и тем же именем может быть доступен из производного класса. Исправить ситуацию можно явно указав принадлежность с помощью "::"
class B1
{
public:
void g(int) { }
};

class B2
{
public:
void g() { }
};

class D : public B1, public B2
{
public:
int i;
B1::g;
B2::g;
};

int main()
{
D dobj;
D *dptr = &dobj;
dptr->g();
dptr->g(3);
}