C ++ неявно вызывает функцию Когда? и как? - PullRequest
3 голосов
/ 01 октября 2009

У меня есть пара вопросов.

Все ли функции внутри функций-членов класса? или только те, которым предшествует объявление "друг"?

Значение функций-членов состоит в том, что они не могут быть доступны любым другим классам правильно?

В чем разница между неявным и явным вызовом?

Какие функции могут или не могут быть вызваны неявно?

Я надеялся увидеть пример неявного и явного вызова.

РЕДАКТИРОВАТЬ: Спасибо за отличные ответы, было много кусочков, которые ответили на мой вопрос и спасибо за ссылки на книги. Я буду читать их.

Ответы [ 9 ]

7 голосов
/ 01 октября 2009

Чтение Мышление на С ++, Брюс Экель . Это отличная, очень удобочитаемая электронная книга, которую можно бесплатно скачать, и она ответит на все ваши вопросы.

4 голосов
/ 01 октября 2009

Конструкторы, деструкторы и operator type() функции вызываются неявно.

3 голосов
/ 01 октября 2009

Существует небольшая разница между неявными и явными вызывающими функциями. Рассмотрим следующий контрольный пример из стандартного документа

struct A { };
void operator + (A, A);

struct B {
  void operator + (B);
  void f ();
};

A a;
void B::f() {
  operator+ (a,a); // ERROR – global operator hidden by member
  a + a; // OK – calls global operator+
}

Первый сбой, потому что вы дали имя функции в явном виде, и имя будет найдено «наизнанку»: сначала в функции, затем в ее классе, а затем в глобальной области видимости.

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

Явные вызовы функций также никогда не выберут встроенный оператор. Вы не можете сделать operator+(10, 12); например. В общем, я бы всегда предпочел неявные вызовы функций.


Все ли функции внутри функций-членов класса? Или только те, которым предшествует объявление «друг»?

Как уже сказал кто-то другой, функции-друзья не являются членами класса, который содержит объявление, даже если функции определены в объявлении тоже

struct A {
    friend void f() {
      std::cout << "member of the global namespace" << std::endl;
    }

    void g() {
      std::cout << "member of class A" << std::endl;
    }
};

Лексическая область действия f равна A - это означает, что вы можете ссылаться на (статические) члены или вложенные типы A, не добавляя перед их именами A::.


Что касается специальных функций-членов, то вы можете явно вызывать деструктор или оператор присваивания, в то время как конструкторы нельзя вызывать явно. Их вызовы неявны и являются частью создания нового объекта.

3 голосов
/ 01 октября 2009

Все ли функции внутри класса функции-члены? или только те предшествует объявление "друг"?

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

class myclass
{
    friend void fun(const myclass& obj);
    int x;
};

void fun(const myclass& obj)
{
    std::cout << obj.x; // x is private member
}

В чем разница между неявный и явный вызов?

Когда вы вызываете функцию, используя () operator, это явный вызов. Если вы не делаете это таким образом, это неявный. Пример явного вызова:

fun();

Примеры неявных вызовов:

void someScope(){
    myclass myobject; // constructors called

} // destructor of myobject is called before exiting the function
....
myclass* mySecondObject = new myclass; // constructor called
delete mySecondObject; // destructor called
3 голосов
/ 01 октября 2009

Я думаю, что хорошим началом для вас будет чтение этого сайта: FAQ по C ++ .

Однако, чтобы дать вам краткий ответ: все функции и переменные, объявленные в определении класса, являются членами этого класса. Ключевое слово «друг» имеет особое значение, относящееся к тому, кто имеет доступ к различным членам.

Права доступа контролируются тем, был ли член объявлен в публичном, закрытом или защищенном разделах определения класса.

Чтение FAQ по C ++ должно дать вам хорошее представление о том, как эти части сочетаются друг с другом.

0 голосов
/ 02 октября 2009

Явное означает, что функция будет вызываться только в том случае, если вы специально вызываете ее в своем исходном коде.

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

Например:

class FooA
{
public:
   FooA();
};

class FooB
{
public:
   FooB();
   explicit FooB(const FooA &other);
};

Теперь предположим, что у вас есть эта функция:

void MyFunc(FooB &var) { ... }

и этот код

void main()
{
   FooA bar;
   MyFunc(bar);

   FooB foo(bar);
}

Обычно компилятор может создавать тип FooA из типа FooB через конструктор, если у вас нет ключевого слова "явный". Теперь он будет жаловаться, что не знает, как сделать FooA из fooB, когда вы передаете его в MyFunc ().

Однако он не будет жаловаться на конструкцию foo из bar, потому что вы явно ее назвали.

0 голосов
/ 01 октября 2009

Чтобы ответить на вопросы:

Все функции в объявлении класса являются функциями-членами, кроме тех, которые отмечены как «друг». Это другие классы или функции, которые могут получить доступ к внутренним класс, о котором идет речь.

Функции-члены - это функции, которые делают что-то относящееся к классу. Они имеют значение private по умолчанию или если они идут после обозначения private:, что означает, что к ним могут обращаться только другие функции в классе. Другими модификаторами доступа являются protected, означающие, что к ним могут обращаться другие функции класса, а также функции в классах, которые наследуются от этого класса, и public, означающие, что они являются честной игрой для всех. Классы или функции, которые определены как friend, могут обращаться к private и protected данным и элементам функций.

Я не знаю, что вы подразумеваете под неявным и явным. Одно из возможных значений связано с ключевым словом explicit, которое можно применять к конструкторам.

В классе Foo, предположим, я объявляю

Foo(int i);
explicit Foo(const char * s);

Это означает, что, если я упомяну где-нибудь значение int, компилятор может обработать его, как если бы это было Foo, но для того, чтобы рассматривать строку как значение, я должен был бы явно указать это, так что если я есть

f(Foo f);

объявлено где-то, затем

f(1);
f(Foo("foo"));

являются законными звонками, но

f("foo");

нет.

Исходя из характера ваших вопросов, я бы сказал, что вам нужна хорошая элементарная книга по C ++. Существует вопрос StackOverflow о превосходных книгах по C ++ , которые я бы порекомендовал в дополнение к C ++ FAQ Lite . Вы можете учиться, изучая программы и задавая здесь случайные вопросы, но это займет больше времени, и вы будете упускать вещи.

0 голосов
/ 01 октября 2009

Все ли функции внутри функций-членов класса? Это зависит от того, что вы подразумеваете под «Внутри». Вы можете определить автономные функции (не являющиеся членами) в пространстве имен класса. Функции, объявленные как «друг», являются , а не функциями-членами (если бы они были, их не нужно было бы объявлять как друзей). Функции, не являющиеся друзьями, в определении класса являются функциями-членами.

Функции-члены с «публичным» доступом доступны для других классов и автономных функций.

Неявные вызовы функций часто возникают в контексте преобразований типов и построения объектов. Вот пример :

class BigBuffer
{
public:
 BigBuffer(int initialValue)
   { memset(buffer, initialValue, sizeof(buffer)); }
private:
 char buffer[65536];
};

extern void Foo(const BigBuffer& o);

void oops()
{
 Foo(3);
}

Foo (3) приводит к неявному вызову конструктора BigBuffer для преобразования целое число 3 в объекте BigBuffer, который ожидает функция Foo.

0 голосов
/ 01 октября 2009

Не уверен, что вы подразумеваете под неявным и явным ...

Члены класса по умолчанию закрыты. Добавление спецификации друга позволяет другому классу получать доступ к закрытым членам. Например:

class A
{
   void hidden();
   friend class B;
};

class B
{
   void callIntoA( A& a )
   {
       a.hidden();
   }
};

Или, если вы хотите сделать что-то общедоступным, вы можете указать следующий раздел: public:

class A
{
    void hidden();

public:
    void notHidden();
    void alsoNotHidden();

private:
    void alsoHidden();
};
...