也许这在某处得到了解答,我只是不知道要搜索它的词。我试图理解我是否看到了一个错误或者我是否理解了减号运算符。是否在标题中赋值,导致编译器跳过' - '?
我的项目具有以下结构,包括生成的文件:
test ├── src │ ├── TipCoordinate.cpp │ └── TipCoordinate.hpp └── UnitTest ├── main.cpp ├── main.o ├── Makefile ├── TipCoordinate.o ├── UnitTest.pro └── UnitTest.pro.user
我在类标题中定义了一个常量,如下所示:
class TipCoordinate{
public:
TipCoordinate() {};
~TipCoordinate() {};
void Z(const float z);
private:
static const float sREFERENCE_SPHERE_RADIUS = 12;
};
我的类cpp文件中的以下代码将无法编译:
#include "TipCoordinate.hpp"
void TipCoordinate::Z(const float z){
float z_origin_ = -sREFERENCE_SPHERE_RADIUS;
}
我收到错误.../model/TipCoordinate.cpp:143: error: undefined reference to 'TipCoordinate::sREFERENCE_SPHERE_RADIUS'
但是,如果我按照以下方式进行更改,那么非常高兴:
#include "TipCoordinate.hpp"
void TipCoordinate::Z(const float z){
float z_origin_ = -1*sREFERENCE_SPHERE_RADIUS;
}
或者,这也适用:
#include "TipCoordinate.hpp"
void TipCoordinate::Z(const float z){
float z_origin_ = 0-sREFERENCE_SPHERE_RADIUS;
}
我认为亚当罗森菲尔德的答案解决了我的问题,但是为了回应一些评论,我用一个最小的,完整的例子替换了上面的摘录,重现了这个问题。正如一些人猜测的那样,我正在使用g ++。版本是g ++(Ubuntu / Linaro 4.5.2-8ubuntu4)4.5.2,似乎优化器受到影响,因为我正在使用“Qt Creator 2.1.0,基于Qt 4.7.2(32位),内置于2011年3月11日“。这是我的项目文件:
QT -= gui
INCLUDEPATH += ../src
TEMPLATE = app
SOURCES += main.cpp \
../src/TipCoordinate.cpp
HEADERS += \
../src/TipCoordinate.hpp
我的主文件只是以下内容,但将项目模板更改为lib并删除主文件会导致问题消失。
int main() { return 0; }
我怀疑Qt Creator很重要,因为除了更改模板之外,当我改变其他看似无关的因素时,问题就会消失或重新出现。出于这个原因,我在下面包含了Qt Creator生成的Makefile:
#############################################################################
# Makefile for building: UnitTest
# Generated by qmake (2.01a) (Qt 4.7.3) on: Sun Oct 14 15:05:23 2012
# Project: UnitTest.pro
# Template: app
# Command: /usr/local/Trolltech/QtEmbedded-4.7.3/bin/qmake -spec /usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/qws/linux-x86-g++ CONFIG+=debug QMLJSDEBUGGER_PATH=/usr/share/qtcreator/qml/qmljsdebugger -o Makefile UnitTest.pro
#############################################################################
####### Compiler, tools and options
CC = gcc
CXX = g++
DEFINES = -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_SHARED
CFLAGS = -pipe -g -Wall -W -D_REENTRANT $(DEFINES)
CXXFLAGS = -pipe -g -Wall -W -D_REENTRANT $(DEFINES)
INCPATH = -I/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/qws/linux-x86-g++ -I. -I/usr/local/Trolltech/QtEmbedded-4.7.3/include/QtCore -I/usr/local/Trolltech/QtEmbedded-4.7.3/include/QtNetwork -I/usr/local/Trolltech/QtEmbedded-4.7.3/include -I../src -I.
LINK = g++
LFLAGS = -Wl,-rpath,/usr/local/Trolltech/QtEmbedded-4.7.3/lib
LIBS = $(SUBLIBS) -L/usr/local/Trolltech/QtEmbedded-4.7.3/lib -lQtNetwork -L/usr/local/Trolltech/QtEmbedded-4.7.3/lib -lQtCore -lpthread
AR = ar cqs
RANLIB =
QMAKE = /usr/local/Trolltech/QtEmbedded-4.7.3/bin/qmake
TAR = tar -cf
COMPRESS = gzip -9f
COPY = cp -f
SED = sed
COPY_FILE = $(COPY)
COPY_DIR = $(COPY) -r
STRIP = strip
INSTALL_FILE = install -m 644 -p
INSTALL_DIR = $(COPY_DIR)
INSTALL_PROGRAM = install -m 755 -p
DEL_FILE = rm -f
SYMLINK = ln -f -s
DEL_DIR = rmdir
MOVE = mv -f
CHK_DIR_EXISTS= test -d
MKDIR = mkdir -p
####### Output directory
OBJECTS_DIR = ./
####### Files
SOURCES = main.cpp \
../src/TipCoordinate.cpp
OBJECTS = main.o \
TipCoordinate.o
DIST = /usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/common/g++.conf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/common/unix.conf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/common/linux.conf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/common/qws.conf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/qconfig.pri \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/modules/qt_webkit_version.pri \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/qt_functions.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/qt_config.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/exclusive_builds.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/default_pre.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/debug.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/default_post.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/warn_on.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/qt.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/unix/thread.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/moc.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/resources.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/uic.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/yacc.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/lex.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/include_source_dir.prf \
UnitTest.pro
QMAKE_TARGET = UnitTest
DESTDIR =
TARGET = UnitTest
first: all
####### Implicit rules
.SUFFIXES: .o .c .cpp .cc .cxx .C
.cpp.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
.cc.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
.cxx.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
.C.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
.c.o:
$(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<"
####### Build rules
all: Makefile $(TARGET)
$(TARGET): $(OBJECTS)
$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS)
Makefile: UnitTest.pro /usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/qws/linux-x86-g++/qmake.conf /usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/common/g++.conf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/common/unix.conf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/common/linux.conf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/common/qws.conf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/qconfig.pri \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/modules/qt_webkit_version.pri \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/qt_functions.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/qt_config.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/exclusive_builds.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/default_pre.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/debug.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/default_post.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/warn_on.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/qt.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/unix/thread.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/moc.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/resources.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/uic.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/yacc.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/lex.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/include_source_dir.prf \
/usr/local/Trolltech/QtEmbedded-4.7.3/lib/libQtNetwork.prl \
/usr/local/Trolltech/QtEmbedded-4.7.3/lib/libQtCore.prl
$(QMAKE) -spec /usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/qws/linux-x86-g++ CONFIG+=debug QMLJSDEBUGGER_PATH=/usr/share/qtcreator/qml/qmljsdebugger -o Makefile UnitTest.pro
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/common/g++.conf:
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/common/unix.conf:
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/common/linux.conf:
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/common/qws.conf:
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/qconfig.pri:
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/modules/qt_webkit_version.pri:
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/qt_functions.prf:
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/qt_config.prf:
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/exclusive_builds.prf:
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/default_pre.prf:
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/debug.prf:
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/default_post.prf:
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/warn_on.prf:
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/qt.prf:
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/unix/thread.prf:
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/moc.prf:
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/resources.prf:
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/uic.prf:
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/yacc.prf:
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/lex.prf:
/usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/features/include_source_dir.prf:
/usr/local/Trolltech/QtEmbedded-4.7.3/lib/libQtNetwork.prl:
/usr/local/Trolltech/QtEmbedded-4.7.3/lib/libQtCore.prl:
qmake: FORCE
@$(QMAKE) -spec /usr/local/Trolltech/QtEmbedded-4.7.3/mkspecs/qws/linux-x86-g++ CONFIG+=debug QMLJSDEBUGGER_PATH=/usr/share/qtcreator/qml/qmljsdebugger -o Makefile UnitTest.pro
dist:
@$(CHK_DIR_EXISTS) .tmp/UnitTest1.0.0 || $(MKDIR) .tmp/UnitTest1.0.0
$(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/UnitTest1.0.0/ && $(COPY_FILE) --parents ../src/TipCoordinate.hpp .tmp/UnitTest1.0.0/ && $(COPY_FILE) --parents main.cpp ../src/TipCoordinate.cpp .tmp/UnitTest1.0.0/ && (cd `dirname .tmp/UnitTest1.0.0` && $(TAR) UnitTest1.0.0.tar UnitTest1.0.0 && $(COMPRESS) UnitTest1.0.0.tar) && $(MOVE) `dirname .tmp/UnitTest1.0.0`/UnitTest1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/UnitTest1.0.0
clean:compiler_clean
-$(DEL_FILE) $(OBJECTS)
-$(DEL_FILE) *~ core *.core
####### Sub-libraries
distclean: clean
-$(DEL_FILE) $(TARGET)
-$(DEL_FILE) Makefile
check: first
mocclean: compiler_moc_header_clean compiler_moc_source_clean
mocables: compiler_moc_header_make_all compiler_moc_source_make_all
compiler_moc_header_make_all:
compiler_moc_header_clean:
compiler_rcc_make_all:
compiler_rcc_clean:
compiler_image_collection_make_all: qmake_image_collection.cpp
compiler_image_collection_clean:
-$(DEL_FILE) qmake_image_collection.cpp
compiler_moc_source_make_all:
compiler_moc_source_clean:
compiler_uic_make_all:
compiler_uic_clean:
compiler_yacc_decl_make_all:
compiler_yacc_decl_clean:
compiler_yacc_impl_make_all:
compiler_yacc_impl_clean:
compiler_lex_make_all:
compiler_lex_clean:
compiler_clean:
####### Compile
main.o: main.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o main.o main.cpp
TipCoordinate.o: ../src/TipCoordinate.cpp ../src/TipCoordinate.hpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o TipCoordinate.o ../src/TipCoordinate.cpp
####### Install
install: FORCE
uninstall: FORCE
FORCE:
我看到一个滚动框已经出现,但如果有办法让它看起来更简洁,我欢迎任何提示。
答案 0 :(得分:5)
您所看到的行为差异在于优化程序。无论出于何种原因,优化器决定优化数学并在某些情况下用浮点常量替换它,但不是所有情况。当它这样做时,不会发生错误,因为变量sREFERENCE_SPHERE_RADIUS
永远不会被引用。
应该发生的是你应该在所有情况下得到“未定义的引用”错误,因为变量sREFERENCE_SPHERE_RADIUS
需要在外面给出一个明确的定义类定义。 C ++标准只允许你给一个static
类成员的初始值设定项,如果它是整数或枚举类型:
// Header file
class TipCoordinate
{
static const float sREFERENCE_SPHERE_RADIUS; // declaration
};
// Source file
const float TipCoordinate::sREFERENCE_SPHERE_RADIUS = 12; // definition
来自C ++03§9.2/ 4:
member-declarator 只有在声明
static
成员(9.4)的情况下才能包含常量初始化程序const
整数或const
枚举类型,请参见9.4.2。
在最新版本的C ++语言C ++ 11中,规则稍微宽松一些,您可以在声明中定义浮点常量,但必须使用constexpr
而不是{{ 1}}。
答案 1 :(得分:1)
(由于认真的思考,我不得不编辑这个答案!所以,希望这不会使任何评论无效。)
假设您显示的代码实际上是完全存在的(完整的最小示例将澄清事情!),那么它就是编译错误,它完全可以编译!
你可以通过各种方式解决这个问题。
首先,既然你有一个标题+一个实现文件,那么只需删除类内声明中的初始化,并将其添加到cpp文件中:
float const TipCoordinate::sREFERENCE_SPHERE_RADIUS = 12.0;
注意,对于一个整数类型的常量,你可以在类内声明中初始化它。此外,使用C ++ 11,您可以使用constexpr
来允许初始化类内声明。无论如何,类中的声明在技术上是纯声明,而cpp文件中的声明(如果有的话)是一个定义(即使没有初始化器,也可能是整数类型的常量)。
对于仅限标题的模块,您可以改为...
static double referenceSphereRadius() { return 12.0; }
或者例如...
template< class Dummy >
class TipCoordinate_constants
{
protected:
static double const referenceSphereRadius;
};
template< class Dummy >
double const TipCoordinate_constants<Dummy>::referenceSphereRadius = 12.0;
class TipCoordinate
private TipCoordinate_constants<void>
{
// ...
};
这些技术也适用于C ++ 03编译器。
请注意不使用SHOUTING UPPERCASE。请为宏名称保留。 C ++不是Java。