0

我想改写这个问题,以便更清楚。我有一种感觉,我的方法通常是错误的

它是否破坏了依赖注入的意图,将共享指针向量的引用传递给构造函数,目的是创建一个新的共享指针并将其推送到向量?

我知道不应在对象内使用新命令。在这种情况下,它创建一个对象但将其存储在外部。

有没有更好的方法来解决这个问题,以便“新”可以留在外面?

斑点标记.h

#ifndef SPOTTINGMARKER_H_INCLUDE
#define SPOTTINGMARKER_H_INCLUDE


class SpottingMarker
{
public:
    SpottingMarker() {;}
            ~SpottingMarker(){;}
    void blah();

    double mPosition;
    double mDuration;
    char* mDescription;
};
    #endif

斑点标记.cpp

#include "SpottingMarker.h"
void blah() {;}

CSVSpottingNotes.h

#ifndef CSVSPOTTINGNOTES_H_INCLUDED
#define CSVSPOTTINGNOTES_H_INCLUDED


#include "SpottingMarker.h"
#include <boost/shared_ptr.hpp>
#include <vector>

typedef boost::shared_ptr<SpottingMarker> spottingMarker_ptr;

class CsvSpottingNotes
{
public:
    CsvSpottingNotes(const char* filename, std::vector<spottingMarker_ptr> &SpottingMarkerSet);
    ~CsvSpottingNotes(){;}
    const char* mFilename;
    const char field_terminator;
    const char line_terminator;
    const char enclosure_char;
};
    #endif

CSVSpottingNotes.cpp

#include "CsvSpottingNotes.h"
#include "SpottingMarker.h"
#include <csv_parser/csv_parser.hpp>
#include <boost/shared_ptr.hpp>

CsvSpottingNotes::CsvSpottingNotes(const char* filename, std::vector<spottingMarker_ptr> &SpottingMarkerSet) :
field_terminator(','),
line_terminator('\n'),
enclosure_char('"')

{
    spottingMarker_ptr aSpottingMarker(new SpottingMarker());
    SpottingMarkerSet.push_back(aSpottingMarker);
}

主文件

#include "CsvSpottingNotes.h"
#include "SpottingMarker.h"
#include <vector>

int main(int argc, char ** argv)
{
    typedef boost::shared_ptr<SpottingMarker> spottingMarker_ptr;
    const char* filename = "AT_92.csv";
    std::vector<spottingMarker_ptr> spottingMarkerSet;
    CsvSpottingNotes structure(filename, spottingMarkerSet);
}
4

1 回答 1

1

首先,为了解决您的直接问题,如果我理解正确,您想知道您是否可以(1)创建具有本地范围的共享指针,(2)将其推到对共享指针向量的引用的后面,以及(3) 让指针指向与创建它时相同的对象。所有这些的答案都是肯定的,而且你几乎可以免费获得这种行为。例如:

void push_shared_pointer(std::vector<boost::shared_ptr<int> > &vector) {
  boost::shared_ptr<int> int_ptr(new int(5));
  vector.push_back(int_ptr);
  *int_ptr = 6;
}

std::vector<boost::shared_ptr<int> > int_vector;
push_shared_pointer(int_vector);

std::cout << *int_vector.back( ) << std::endl;

这会输出 6,因为在函数中,自从我们将共享指针推送到向量后,我们使用本地共享指针来修改引用的 int。由于向量中的共享指针和本地共享指针指向同一个内存位置,因此两个共享指针都会被更新。

至于其余的代码,有几点需要注意。首先,正如其他人所指出的,预处理器守卫是一个问题。其次,您没有限定 SopttingMarker.cpp 中的函数 blah() 来告诉编译它是 SpottingMarker 类中 blah 函数的实现。它应该是:

#include "SpottingMarker.h"

void SpottingMarker::blah() { }

此外,由于您在标题中指出您将提供用户定义的默认构造函数,因此您也应该在 SpottingMarker.cpp 中提供它。

SpottingMarker::SpottingMarker()
  : mPosition(0)
  , mDuration(0)
  , mDescription(NULL)
{ }

第三,既然你在 CsvSpottingNotes.h 中声明了一个析构函数,你应该在 CsvSpottingNotes.cpp 中定义它:

CsvSpottingNotes::~CsvSpottingNotes() {
  // implementation here
}

这些应该是您需要的所有定义,至少根据您的构建日志。

我要注意的最后一件事是,由于三个原因,它看起来不像您以传统方式使用依赖注入。首先,通常当您进行依赖注入时,您会将对注入对象的引用存储在接收器对象中,以便接收器可以在其生命周期内使用。在这里,您将向量注入到 CsvSpottingNotes 中,但您没有在类中存储对它的引用;你只需将一个共享指针推到它上面。

其次,根据我的经验,依赖注入是针对行为抽象的,即将接收者(客户端)对象的行为与使用接口的注入对象的行为分开。这允许您通过注入接口的不同实现来修改客户端的行为。在这种情况下,您没有使用界面;std::vector 在编译时是完全限定的类型,而 CsvSpaottingMarker 不能与任何其他类型一起使用,因此没有理由使用依赖注入。更好的解决方案是将向量存储为 CsvSpottingMarker 的成员。

第三,正如我之前所说,依赖注入主要用于行为抽象,即让客户端对象根据注入到它们的接口的实现而表现不同。std::vector 类不适合依赖注入,因为它不提供行为;相反,它只是保存状态。一般来说,对象的状态应该被封装为对象类的成员,这进一步支持在CsvSpottingMarker类中包含向量。

希望有帮助!

于 2012-05-17T01:48:07.017 回答