菜鸟开始学c++之:多次定义的问题,如何使用类的const static成员

夏涌升 发布于 2013/08/25 13:55
阅读 1K+
收藏 0

一个还没写完的类:如果我把string Secret::charCode,改为const static string Secret::charCode,

并把赋值从Secret类已到类外,在endif前:

const string Secret::charCode = "省略";

在main文件引入的时候,会有错误:

build/Debug/GNU-Linux-x86/main.o:在函数‘__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::string const, std::string> > >::~new_allocator()’中:
/toozy/cpp/test/test_1/main.cpp:14: `Secret::charCode'被多次定义
build/Debug/GNU-Linux-x86/Secret.o:/toozy/cpp/test/test_1/Secret.cpp:147:第一次在此定义
collect2: 错误: ld 返回 1

main文件如下:

#include 
#include 
#include 
#include 
#include "Secret.cpp"
int main(int argc, char** argv) {
    
    try {
        Secret s;
        s.setCode("iloveu");
        string str = "koozytoozy";
        string encodeStr = s.encode(&str);
        string decodeStr = s.decode(&encodeStr);
        cout<<encodeStr<<endl;
        cout<<decodeStr<<endl;
        return 0;
    } catch(out_of_range &e){
        cout<<e.what()<<endl;
    }
}

Secret.cpp如下:

#include <string>
#include <map>
#include <list>
#include <iostream>
using namespace std;
#ifndef _CLASS_SECRET
#define _CLASS_SECRET 1

class Secret {
public:
    Secret() {
        charCode = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-";
    }

    void setCode(const string argCode) {
        code = argCode;
    }

    const list<map<string, string >> getList() {
        return getList(1);
    }

    const list<map<string, string >> getList(int argPage) {

    };

    int update(int argIndex, string argField, string argValue) {

    };

    int update(int argIndex, map<string, string> argData) {
    };

    int add(map<string, string> argData) {
    };

    map<string, string> get(int argIndex) {
    };

    map<string, string> get(string argName) {
    };

    const string encode(const string* argStr) {
        string firstStr;
        string rsStr;
        string appendStr;
        string::const_iterator oStrIterB = argStr->begin();
        string::const_iterator oStrIterE = argStr->end();
        string::const_iterator keyIterB = code.begin();
        string::const_iterator keyIterE = code.end();
        while (oStrIterB != oStrIterE) {
            if (keyIterB == keyIterE) {
                keyIterB = code.begin();
            }
            firstStr += *oStrIterB ^ *keyIterB;
            ++oStrIterB;
            ++keyIterB;
        }
        size_t firstStrL = firstStr.length();
        switch (firstStrL % 3) {
            case 1:
                firstStr.insert(firstStrL - 1, 2, '0');
                appendStr = "==";
                break;
            case 2:
                firstStr.insert(firstStrL - 2, 1, '0');
                appendStr = "=";
                break;

        }
        string::iterator strB = firstStr.begin();
        string::iterator strE = firstStr.end();

        while (strB != strE) {
            rsStr += charCode[(*strB) >> 2];
            rsStr += charCode[((*strB & 0x03) << 4) | (*(++strB) >> 4)];
            rsStr += charCode[((*strB & 0x0f) << 2) | (*(++strB) >> 6)];
            rsStr += charCode[*strB & 0x3f];
            ++strB;
        }
        rsStr += appendStr;
        return rsStr;
    };

    const string decode(const string* argStr) {
        if (codeChar.size() == 0) {
            int charCodeLen = charCode.size();
            for (int i = 0; i < charCodeLen; i++) {
                codeChar[charCode[i]] = i;
            }
        }
        string firstStr;
        string rsStr;
        int l = argStr->length();

        int appendL = 0;
        if ((*argStr)[l - 2] == '=') {
            appendL = 2;
            l -= 4;
        } else if ((*argStr)[l - 1] == '=') {
            appendL = 1;
            l -= 4;
        }
        l -= appendL;
        int tempCode[4] = {0};
        for (int strI = 0; strI < l; ++strI) {
            tempCode[0] = codeChar[(*argStr)[strI]];
            tempCode[1] = codeChar[(*argStr)[++strI]];
            tempCode[2] = codeChar[(*argStr)[++strI]];
            tempCode[3] = codeChar[(*argStr)[++strI]];
            firstStr += char((tempCode[0] << 2) | (tempCode[1] >> 4));
            firstStr += char(((tempCode[1]&0x0f) << 4) | ((tempCode[2]&0x3c) >> 2));
            firstStr += char((tempCode[2] << 6) | tempCode[3]);
        }
        switch (appendL) {
            case 1:
                firstStr += char(((codeChar[(*argStr)[++l]]&0x0f) << 4) | ((codeChar[(*argStr)[++l]]&0x3c) >> 2));
                firstStr += char((codeChar[(*argStr)[l]] << 6) | codeChar[(*argStr)[++l]]);
                break;
            case 2:
                firstStr += char((codeChar[(*argStr)[++++l]] << 6) | codeChar[(*argStr)[++l]]);
                break;
        }
        string::iterator oStrIterB = firstStr.begin();
        string::iterator oStrIterE = firstStr.end();
        string::iterator keyIterB = code.begin();
        string::iterator keyIterE = code.end();
        while (oStrIterB != oStrIterE) {
            if (keyIterB == keyIterE) {
                keyIterB = code.begin();
            }
            rsStr += *oStrIterB ^ *keyIterB;
            ++oStrIterB;
            ++keyIterB;
        }
        return rsStr;
    };
    string charCode;
    map<char, int> codeChar;
private:
    string code = "meiyou mima";
    int pageSize = 20;
    int page = 1;
    list<map<string, string >> data;
    string dataFile = "data/my";
};
#endif
加载中
0
中山野鬼
中山野鬼

引用来自“夏涌升”的答案

引用来自“中山野鬼”的答案

你两个cpp 文件都被编译了。其中一个是#include到main里的。所以重复了。哈。

我只在main.cpp里include一次Secret.cpp ,而且Secret.cpp里有用到#ifndef #endif。。。

怎么会出现重复引入呢?

我刚接触有很多不明白,求指点。。。

你说的情况是防止#include 某个文件连续调用。但不会一次都不写入main.cpp。哈。至于编译器,每次独立工作是针对一个源文件。 secret.cpp在main.cpp中被复制,独立编译过一次。这个不会影响secret.cpp自身编译时,对#define的设置。哈。
0
中山野鬼
中山野鬼
你两个cpp 文件都被编译了。其中一个是#include到main里的。所以重复了。哈。
0
夏涌升
夏涌升

引用来自“中山野鬼”的答案

你两个cpp 文件都被编译了。其中一个是#include到main里的。所以重复了。哈。

我只在main.cpp里include一次Secret.cpp ,而且Secret.cpp里有用到#ifndef #endif。。。

怎么会出现重复引入呢?

我刚接触有很多不明白,求指点。。。

0
夏涌升
夏涌升

引用来自“中山野鬼”的答案

引用来自“夏涌升”的答案

引用来自“中山野鬼”的答案

你两个cpp 文件都被编译了。其中一个是#include到main里的。所以重复了。哈。

我只在main.cpp里include一次Secret.cpp ,而且Secret.cpp里有用到#ifndef #endif。。。

怎么会出现重复引入呢?

我刚接触有很多不明白,求指点。。。

你说的情况是防止#include 某个文件连续调用。但不会一次都不写入main.cpp。哈。至于编译器,每次独立工作是针对一个源文件。 secret.cpp在main.cpp中被复制,独立编译过一次。这个不会影响secret.cpp自身编译时,对#define的设置。哈。

虽然听不懂不过应该也是这样的了。

我的理解是:ide首先设定把 资源类.cpp 生成一个 o文件引入 main里去,然后我main里又引入了这个文件,所以重复定义了,如果main引入的是h文件就不会。。。

所以我把Secret.cpp 分出一个 Secret.h出来,就没问题了。。。。

刚开始本来是分开的,但是生成时包语法分析错误,刚才把list<map<string,string>>后面的>>用空格分开就好了。。。

0
中山野鬼
中山野鬼

引用来自“夏涌升”的答案

引用来自“中山野鬼”的答案

引用来自“夏涌升”的答案

引用来自“中山野鬼”的答案

你两个cpp 文件都被编译了。其中一个是#include到main里的。所以重复了。哈。

我只在main.cpp里include一次Secret.cpp ,而且Secret.cpp里有用到#ifndef #endif。。。

怎么会出现重复引入呢?

我刚接触有很多不明白,求指点。。。

你说的情况是防止#include 某个文件连续调用。但不会一次都不写入main.cpp。哈。至于编译器,每次独立工作是针对一个源文件。 secret.cpp在main.cpp中被复制,独立编译过一次。这个不会影响secret.cpp自身编译时,对#define的设置。哈。

虽然听不懂不过应该也是这样的了。

我的理解是:ide首先设定把 资源类.cpp 生成一个 o文件引入 main里去,然后我main里又引入了这个文件,所以重复定义了,如果main引入的是h文件就不会。。。

所以我把Secret.cpp 分出一个 Secret.h出来,就没问题了。。。。

刚开始本来是分开的,但是生成时包语法分析错误,刚才把list<map<string,string>>后面的>>用空格分开就好了。。。

你去理解下预处理主要做什么哈。不同源文件对应的.o,只会在 连接时会有相互作用,比如找不到对应函数啊。或者函数重名啊。你的问题就是存在两个.o里都有相同的编译对象,所以连接时就挂了。你要不信,可以把serret.cpp从你的工程中拿掉,一切就又恢复正常了。哈。
返回顶部
顶部