Является ли параметр const value в определении, но не в объявлении, действительно C ++? - PullRequest
3 голосов
/ 20 апреля 2009

Это похоже на (но отличается от) этот вопрос .

Вот простой тестовый код, иллюстрирующий некоторые странности, которые я обнаружил в Sun CC:

//---------------main.cpp
#include "wtc.hpp"

int main(int, char**)
{
  testy t;
  t.lame(99);
  return 0;
}
//--------------wtc.hpp
#ifndef WTC_HPP_INCLUDED
#define WTC_HPP_INCLUDED

class testy
{
public:
  void lame(int );
};

#endif 

//---------------wtc.cpp
#include <iostream>
#include "wtc.hpp"

void testy::lame(const int a)
{
  std::cout << "I was passed " << a << "\n";
}

//---------------makefile
#CXX=CC
CXX =g++
#CXXFLAGS= -g 
CXXFLAGS= -g3 -Wall -Werror

OBJECTS=$(patsubst %.cpp,%.o,$(wildcard *.cpp))

all : $(OBJECTS)
    $(CXX) $(CXXFLAGS) -o $@ $^

.PHONY: clean
clean :
    rm *.o

Когда это было скомпилировано с использованием g ++, оно компилирует, связывает и делает то, что вы ожидаете при запуске. Вы также можете добавить ++ a; в testy :: lame () и компилятор будет жаловаться на изменение переменной только для чтения (как и должно быть).

Однако, когда я компилирую с использованием CC, я получаю следующую ошибку компоновщика:

CC -g   -c -o main.o main.cpp
CC -g   -c -o wtc.o wtc.cpp
CC -g -o all main.o wtc.o
Undefined                       first referenced
 symbol                             in file
void testy::lame(int)               main.o
ld: fatal: Symbol referencing errors. No output written to all
make: *** [all] Error 1

проверяя объектный код с помощью nm и C ++ фильтром, я обнаружил, что версия g ++ создает символ testy :: lame (int), тогда как CC создает testy :: lame (const int), следовательно, ошибка компоновщика.

Я посмотрел его в книге Страуструпа, но не могу найти упомянутую технику (это не значит, что ее там нет!); так это действительно ошибка компилятора, или просто взлом, который работает везде, кроме Solaris?

Ответы [ 7 ]

23 голосов
/ 20 апреля 2009

Это похоже на проблему компилятора в CC. Стандарт C ++ гласит (в 13.1 перегружаемых объявлениях):

Объявления параметров, которые отличаются только наличием или отсутствием const и / или volatile, эквивалентны. То есть спецификаторы const и volatile для каждого типа параметра игнорируются при определении, какая функция объявляется, определяется или вызывается.

Но есть модификаторы const / volatile, которые могут участвовать в перегрузке, как стандарт упоминает вскоре после этого:

При этом игнорируются только спецификаторы типа const и volatile на самом внешнем уровне спецификации типа параметра; Спецификаторы типа const и volatile, скрытые в спецификации типа параметра, имеют большое значение и могут использоваться для различения объявлений перегруженных функций.

4 голосов
/ 20 апреля 2009

'const' в параметре 'const int' должен игнорироваться компилятором. Однако разница между объявлением и определением заключается, по меньшей мере, в плохом стиле.

1 голос
/ 20 апреля 2009

Я понимаю, что это разрешено, потому что это мало что меняет для звонящего. Это не функция, которая является константой, а скорее параметр, и вы делаете дополнение в определении. Таким образом, const, который вы фактически добавили, влияет только на реализацию

См. вопрос .

0 голосов
/ 22 сентября 2012

См. Стандарты кодирования C ++ by Alexandrescu # 15. Это должно работать по его словам. Const не позволяет разработчику функции изменять входную переменную. IMO переменная должна оставаться константой внутри функции. Если вам нужна переменная, объявите ее. Оптимизатор избавится от вас за вас.

int temp = a;

Поскольку здесь это не работает, я советую своему классу использовать (const int a) как в прототипе, так и в реализации. Я большой поклонник использования техник, которые работают для всех компиляторов.

0 голосов
/ 20 апреля 2009

const, равное void func1(const int), никак не влияет на функцию, поскольку int передается по значению - создается копия int, и эта копия сохраняется только до вызова функции. Независимо от того, измените ли вы эту копию, это не имеет никакого отношения.

Вы, вероятно, смущены тем фактом, что в void func2(const char*) значение const значимо. Но вы должны признать, что это отличается от void func3(char* const). В первом случае персонаж, на которого указывают, не может измениться; в последнем это указатель, который (не имеет значения) 'const'

0 голосов
/ 20 апреля 2009

Да, const int - это не то же самое, что int.

0 голосов
/ 20 апреля 2009

Я бы всегда совпадал с const как в объявлении, так и в определении. Это уменьшит любые проблемы, потому что подписи будут тогда соответствовать.

...