3

おそらくこれはどこかで答えられており、私はそれを検索するための単語がわからないだけです。バグが発生しているのか、マイナス演算子がわからないのかを理解しようとしています。ヘッダーに定数を割り当てると、コンパイラーが「-」をトリップしますか?

私のプロジェクトは、生成されたファイルを含め、次の構造になっています。

テスト
├──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;
}

Adam Rosenfieldの答えは私の質問に対応していると思いますが、いくつかのコメントに応えて、上記の抜粋を、問題を再現する最小限の完全な例に置き換えました。推測されるように、私は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; }

テンプレートを変更することに加えて、他の一見無関係な要素を変更すると、問題が消えるか、再び現れるため、QtCreatorが重要であると思われます。そのため、QtCreatorで生成された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:

スクロールボックスが表示されているようですが、それをより簡潔に表示する方法があれば、ヒントを歓迎します。

4

2 に答える 2

5

表示される動作の違いは、オプティマイザーにあります。何らかの理由で、オプティマイザーは数学を最適化し、すべての場合ではなく、一部のケースで浮動小数点定数に置き換えることを決定します。sREFERENCE_SPHERE_RADIUSその場合、変数はどこにも参照されないため、エラーは発生しません。

何が起こるべきsREFERENCE_SPHERE_RADIUSかというと、変数にはクラス定義の外で明示的な定義を与える必要があるため、すべての場合で「未定義の参照」エラーが発生するはずです。staticC ++標準では、クラスメンバーが整数型または列挙型の場合にのみ、クラスメンバーの初期化子を指定できます。

// 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は、整数型または列挙型のメンバー(9.4)を 宣言する場合にのみ、定数初期化子を含めることができます。9.4.2を参照してください。staticconstconst

C++言語の最新バージョンであるC++11では、ルールが少し緩く、宣言で浮動小数点定数を定義できますが、のconstexpr代わりにを使用する必要がありconstます。

于 2012-10-12T20:56:41.340 に答える
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コンパイラでも正常に機能します。

SHOUTINGUPPERCASEを使用しないことに注意してください。マクロ名用に予約してください。C++はJavaではありません。

于 2012-10-12T20:53:26.827 に答える