代码改变世界

C++/CLI中class成员声明与实现分开在不同文件时必须添加namespace

2013-10-23 17:53  DVwei  阅读(641)  评论(0编辑  收藏  举报

以下是我的代码:

//TaskConfigFile.h
#pragma once
using namespace System::Collections::Generic;
using namespace System;
using namespace System::IO;
using namespace System::Text;

ref class TaskConfigFile
{
public:
    TaskConfigFile();
    TaskConfigFile(String^ str_link, Int64 file_size, short threads_sum);
    TaskConfigFile(String^ str_link, Int64 file_size);

    String^ link;//下载链接
    String^ fileName;//文件名
    String^ filePath;//文件存储路径
    Int64 fileSize;//文件总大小
    Int64 blockSize;//文件分块大小
    Int64 sumDownloadedSize;//已下载的总大小
    short threadsSum;//线程总数,默认为5

    //以字典记录各分块已下载的大小,key为分块的起始位置(字节),value为此分块已下载的大小
    Dictionary<Int64, Int64>^ blockDownloadedSize;

#ifdef DEBUG
    Debug::Listeners->Add( gcnew TextWriterTraceListener( Console::Out ) );
    Debug::AutoFlush = true;
#endif
    bool Save();//保存配置信息
    bool Load(String^ path);//加载配置信息
};
//TaskConfigFile.cpp
#include "stdafx.h"
#include "TaskConfigFile.h"

TaskConfigFile::TaskConfigFile():
    link(nullptr), fileName(nullptr), fileSize(0L), filePath(nullptr), blockSize(0L), sumDownloadedSize(0L), threadsSum(5)
{
    blockDownloadedSize = gcnew Dictionary<Int64, Int64>(threadsSum);
}

TaskConfigFile::TaskConfigFile(String^ str_link, Int64 file_size, short threads_sum):
    link(str_link), fileSize(file_size), threadsSum(threads_sum), sumDownloadedSize(0)
{
    blockDownloadedSize = gcnew Dictionary<Int64, Int64>(threadsSum);
}

TaskConfigFile::TaskConfigFile(String^ str_link, Int64 file_size):
    link(str_link), fileSize(file_size), threadsSum(5), sumDownloadedSize(0)
{
    blockDownloadedSize = gcnew Dictionary<Int64, Int64>(threadsSum);
}

bool TaskConfigFile::Save()
{
    String^ path = String::Concat(filePath, fileName, ".tmp");
    Stream^ writeStream = gcnew FileStream(path, FileMode::Create, FileAccess::Write);
    if(writeStream == nullptr)
    {
#ifdef DEBUG
        Diagnostics::Debug::WriteLine("文件路径错误!");
#endif
        return false;
    }

    BinaryWriter^ binaryWriter = gcnew BinaryWriter(writeStream, Encoding::ASCII);
    binaryWriter->Write(this->link);
    binaryWriter->Write(this->fileName);
    binaryWriter->Write(this->filePath);
    binaryWriter->Write(this->fileSize);
    binaryWriter->Write(this->blockSize);
    binaryWriter->Write(this->sumDownloadedSize);
    binaryWriter->Write(this->threadsSum);
    for each(KeyValuePair<Int64, Int64> pair in blockDownloadedSize)
    {
        binaryWriter->Write(pair.Key);
        binaryWriter->Write(pair.Value);
    }
    writeStream->Close();
    binaryWriter->Close();
    return true;
}

bool TaskConfigFile::Load(String^ path)
{
    Stream^ readStream = gcnew FileStream(path, FileMode::Open, FileAccess::Read);
    if(readStream == nullptr)
    {
#ifdef DEBUG
        Diagnostics::Debug::Indent();
        Diagnostics::Debug::WriteLine("error: 打开文件失败!");
        Diagnostics::Debug::WriteLine("Paht: {0}", path);
        Diagnostics::Debug::UnIndent();
#endif
        return false;
    }
    BinaryReader^ binaryReader = gcnew BinaryReader(readStream);
    try
    {
        link = binaryReader->ReadString();
        fileName = binaryReader->ReadString();
        filePath = binaryReader->ReadString();
        fileSize = binaryReader->ReadInt64();
        blockSize = binaryReader->ReadInt64();
        sumDownloadedSize = binaryReader->ReadInt64();
        threadsSum = binaryReader->ReadInt16();
        for(int i = 0; i < threadsSum; ++i)
        {
            Int64 key = binaryReader->ReadInt64();
            Int64 value = binaryReader->ReadInt64();
            blockDownloadedSize->Add(key, value);
        }
    }
    catch(EndOfStreamException^ ex)
    {
#ifdef DEBUG
        Diagnostics::Debug::Indent();
        Diagnostics::Debug::WriteLine("The end of the stream is reached."); 
        Diagnostics::Debug::WriteLine(ex->Message);
        Diagnostics::Debug::Unindent();
#endif
        readStream->Close();
        binaryReader->Close();
        return true;
    }

    return true;
    
}

我将他们放在同一个文件就能编译通过。一旦分开就会出现链接错误:

 

这是因为.NET以程序集作为编译单元,每一个程序集里类的成员声明与定义必须在同一个namespace下,而这两个文件中并没有声明namespace,所以链接器找不到TaskConfigFile Class成员的实现代码。

必须将它们声明在同一个namspace中:

//TaskConfigFile.h
namespace xxx
{
    //..............      
}


//TaskConfigFile.cpp
using namespace xxx;