1

私はこのような多くの質問を読みましたが、私の質問が違うかどうかは 100% わかりません。私は正しい答えをかなり探しましたが、ほとんどの答えはマクロガードに関するものでした. から派生したカスタム文字列クラスがstd::stringあり、後でそのプロジェクトを実際の世界で使用していたので、機能を拡張するためだけに std::string を派生させたくありませんでした。そこで、関数を customString.h から utils_string.h に移動しました。定義は次のとおりです。

#ifndef OPS_TOOLKIT_UTILS_STRING_H
#define OPS_TOOLKIT_UTILS_STRING_H
#include <string>
#include <algorithm>
#include <vector>

namespace utils{
  namespace string{

const std::string kilikeDelimiter = "%";

void tolower(std::string& str){
    //CODE
}

bool iequals(const std::string& str1,const std::string& str2){
    //CODE
}
bool ilike(const std::string& str,const std::string& pattern){
    //CODE
}
std::string prependAndAppendILikeDelimiter(const std::string& str) {
    //CODE
}
} //namespace string
} //namespace utils

#endif

そして、私は文句を言います.これ...first defined hereはコンパイラからの正確な出力です. 注:ここにはクラスがありません

/tmp/ccCFVTXP.o: 関数内utils::string::tolower(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)': listings.cpp:(.text+0x0): multiple definition ofutils::string::tolower(std::basic_string, std::allocator >&)' /tmp/cczDtRdT.o:listing.cpp:(.text+0x0): 最初に定義ここで /tmp/ccCFVTXP.o: 関数内utils::string::iequals(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)': listings.cpp:(.text+0x55): multiple definition ofutils::string::iequals(std::basic_string, std::allocator > const&, std::basic_string, std::allocator > const&)' /tmp/cczDtRdT.o: list.cpp:(.text+0x55): ここで最初に定義 /tmp/ccCFVTXP.o: 関数内utils::string::ilike(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)': listings.cpp:(.text+0x118): multiple definition ofutils::string::ilike(std::basic_string, std::allocator > const&, std::basic_string, std: :allocator > const&)' /tmp/cczDtRdT.o:listing.cpp:(.text+0x118): ここで最初に定義 /tmp/ccCFVTXP.o: 関数内utils::string::prependAndAppendILikeDelimiter(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)': listings.cpp:(.text+0x484): multiple definition ofutils::string::prependAndAppendILikeDelimiter(std::basic_string, std ::allocator > const&)' /tmp/cczDtRdT.o:listing.cpp:(.text+0x484):ここで最初に定義された /tmp/ccifZISK.o: 関数内utils::string::tolower(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)': match_count.cpp:(.text+0x0): multiple definition ofutils::string::tolower(std::basic_string, std::allocator >&)' /tmp/cczDtRdT.o:listing.cpp:(.text+0x0): 最初にここで定義 /tmp/ccifZISK.o: でfunction utils::string::iequals(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)': match_count.cpp:(.text+0x55): multiple definition ofutils::string::iequals(std::basic_string, std::allocator > const&, std::basic_string, std::allocator > const&)' /tmp/cczDtRdT.o:listing.cpp:(.text+0x55 ): ここで最初に定義 /tmp/ccifZISK.o: 関数内utils::string::ilike(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)': match_count.cpp:(.text+0x118): multiple definition ofutils::string::ilike(std::basic_string, std::allocator > const&, std::basic_string, std::allocator > const&)' /tmp/ cczDtRdT.o:listing.cpp:(.text+0x118): ここで最初に定義 /tmp/ccifZISK.o: 関数内utils::string::prependAndAppendILikeDelimiter(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)': match_count.cpp:(.text+0x484): multiple definition ofutils::string::prependAndAppendILikeDelimiter(std::basic_string, std::allocator > const&)' /tmp /cczDtRdT.o:listing.cpp:(.text+0x484): ここで最初に定義された collect2: ld は 1 つの終了ステータスを返しました

混乱して申し訳ありませんが、同様の問題に遭遇した人のために何も見逃したくありませんでした.

もう一つ; ここでは、match_count.cpp * listing.cpp * およびListings.cpp と表示れており、::utils::string::function() で定義されている関数を使用しているだけです。

4

2 に答える 2

4

明示的に指定しない限り、ヘッダー ファイルでコードを定義するinlineことはできません。それ以外の場合 (プリプロセッサが巨大なコピー/貼り付けマシンのように機能するため) #include、.

したがって、それらのそれぞれに追加するか、ヘッダーではなくinline単一の に入れます。.cpp

于 2012-07-17T01:23:38.570 に答える
0

このようなクラスに関数を配置する方がよい場合があります (以下は .h ファイルに移動します)。ネストされた名前空間を使用する方がおそらく一般的です。

#pragma once
#include <string>

namespace utils
{
    class StringUtil
    {
        public:
           static void tolower(std::string& str)
           {
               // code
           }
    };
}
于 2012-07-17T01:38:11.470 に答える