связь с методом struct - PullRequest
       14

связь с методом struct

3 голосов
/ 25 марта 2010

Я обновляю некоторый старый код, который имеет несколько структур POD, которые обнуляют memset (не вините меня ... я не писал эту часть). Часть обновления изменила некоторые из них на классы, использующие частные внутренние указатели, которые теперь стираются с помощью memset.

Поэтому я добавил [не виртуальный] метод reset () к различным структурам и реорганизовал код, чтобы вызывать его вместо этого.

Одна конкретная структура разработала ошибку "неопределенная ссылка на` blah :: reset () '".

Изменение его из структуры в класс исправило ошибку.

При вызове nm для файла .o h имена искаженных функций для этого метода выглядят одинаково (будь то класс или структура).

Я использую g ++ 4.4.1 в Ubuntu.

Я ненавижу мысль, что это может быть ошибка компилятора / компоновщика, но я не уверен, что еще это может быть. Я пропускаю какое-то фундаментальное различие между структурами и классами? Я думал, что единственными значимыми были публичные / частные дефолты и то, как все о них думают.

Обновление: На самом деле это зависит от того, как он объявлен:

typedef struct
{
  ...
  void reset();
} foo;

не будет ссылки.

struct foo
{
  ...
  void reset();
};

ссылки в порядке.

Так, может быть, просто отсутствие понимания с моей стороны о том, как typedefs работает в этом контексте?

Ответы [ 2 ]

2 голосов
/ 25 марта 2010

Я думаю , что ваша проблема (и у меня нет цитаты стандартов, подтверждающей это) состоит в том, что, поскольку ваша структура не имеет имени, ваша функция-член также не имеет глобально идентифицируемое имя.

Хотя вам разрешено использовать имя typedef для представления определения функции-члена, эта функция-член должна быть частью именованного типа, если вы собираетесь связать ее с определением в другом TU.

typedef struct S_ { void reset(); } S;

void S::reset() // OK, but the function actually has id: S_::reset()
{
    // ...
}

typedef struct { void reset(); } T;

void T::reset() // OK, defintion of anonymous struct's reset(),
                // but this isn't an id that can cross TUs.
{
    // ...
}

Редактировать: Впрочем, это может быть ошибка gcc.

7.1.3 [dcl.typedef] Если объявление typedef определяет и безымянный класс (...), первое имя-typedef , объявленное объявлением как этот тип класса (...) используется для обозначения типа класса (...) только для целей связывания (3.5).

Edit:

Или gcc может быть прав. В то время как класс имеет внешнюю связь через свое имя определения типа (3.5 / 4), функция-член имеет внешнюю связь только в том случае, если имя класса имеет внешнюю связь. Хотя класс имеет внешнюю связь и имеет имя только для целей связи, он все равно является безымянным классом , поэтому его функции-члены не имеют связи.

1 голос
/ 25 марта 2010

Конечно, второе объявление - это «правильный» C ++ способ ведения дел. Тем не менее, это ссылки для меня с g ++ 4.4.1:

typedef struct {
    void f() {}
} S;


int main() {
    S s;
    s.f();
}

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

Редактировать: ОК, минималистский код, который воспроизводит проблему:

// str.h
typedef struct {
    void f();
} S;

// str.cpp
#include "str.h"     
void S :: f() {
}

// sm.cpp
#include "str.h"    
int main() {
    S s;
    s.f();
}

Скомпилировано с:

g++ sm.cpp str.cpp

Ошибка:

undefined reference to S::f()

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...