Ответ 1
Предположим, вы хотите взять адрес функции-члена size()
, тогда вы должны написать это:
auto address = &demo::size;
Но вполне может быть адресом данных-членов size
. Неоднозначная ситуация. Следовательно, это запрещается спецификацией языка.
Это не означает, что комитет С++ не смог прийти к решению, но я полагаю, что нет никакого существенного выигрыша в этом. Следовательно, Стандарт просто запретил это, чтобы все было просто.
Кроме того, разница между данными-членами и функцией-членом становится менее различимой визуально, если объявить функцию-член size()
как:
typedef void fun_type();
struct demo
{
fun_type size; //It looks like a member-data, but it a member-function
};
void demo::size() //define the member function
{
std::cout << "It is crazy!" << std::endl;
}
int main()
{
demo d;
d.size(); //call the function!
}
Вывод:
Это безумие!
Смотрите онлайн-демонстрацию: http://ideone.com/ZjwyJ
Теперь, если мы сможем реализовать функции-члены, как описано выше, тогда становится очевидным даже невооруженным глазом, что вы не можете добавить другого члена с тем же именем, что:
struct demo
{
fun_type size;
int size; //error - choose a different name for the member!
};
Подождите. Это не совсем правильно, так как история еще не закончена. Что-то менее очевидное мне нужно добавить здесь. Вы можете добавить более одного члена с тем же именем:
typedef void fun_type0();
typedef void fun_type1(int a);
typedef void fun_type2(int a, int b);
struct demo
{
fun_type0 member; //ok
fun_type1 member; //ok
fun_type2 member; //ok
};
Это вполне допустимый код, так как каждый член является функцией другого типа, поэтому вы можете определить их как:
void demo::member()
{
std::cout << "member()" << std::endl;
}
void demo::member(int a)
{
std::cout << "member(" << a << ")" << std::endl;
}
void demo::member(int a, int b)
{
std::cout << "member(" << a << ", "<< b << ")" << std::endl;
}
Тестовый код:
int main()
{
demo d;
d.member();
d.member(10);
d.member(200,300);
}
Вывод:
member()
member(10)
member(200, 300)
Онлайн-демонстрация: http://ideone.com/OM97Q
Заключение...
Вы можете добавлять члены с тем же именем, если они работают от разных типов. Это активируется функцией, называемой функцией-функцией-перегрузкой (или простой перегрузкой функций) 1.
1. К сожалению, язык не предоставляет аналогичную функцию, например, пересылку данных-члена, для данных-членов, и язык не обеспечивает перекрестную-перегрузку (что позволяет членам-членам и членам-членам иметь одно и то же имя — дело в вопросе).
Итак, возникает вопрос, естественно ли возникает проблема двусмысленности? Да, так и есть. Но следует отметить, что комитет С++ разработал решение для решения этой проблемы двусмысленности, потому что они увидели огромный выигрыш в этом (в случае перегрузки функций).
Но вопрос в вопросе остается неоднозначным, поскольку комитет не придумал решение, поскольку они не видели никакого огромного преимущества при этом (как отмечалось ранее). Кроме того, когда я сказал, что "комитет С++ разработал решение", я НЕ имею в виду, что решение было стандартизировано, я просто имею в виду, что они знали, как компиляторы могут его решить, и насколько сложным будет решение.