【问题标题】:Implement C++ class method that draws on multiple other non-inherited classes?实现利用多个其他非继承类的 C++ 类方法?
【发布时间】:2017-12-03 21:47:17
【问题描述】:

所以,我将尽最大努力定义我的问题,所以请多多包涵。我正在从事一项基本的财务任务,其中我为不同的基类制作了多个头文件:它们是AssetsPositionPortfolioAssets 是我的基类,Position 类包括通过前向声明对Assets 对象的引用,Portfolio 类通过前向声明包含对Position 类的类似引用。

现在,我正在尝试在 Portfolio 中创建一个名为 getPortfolioValue 的方法,该方法将根据该对象是否是 Asset 的派生类之一(EquityPreferred)返回投资组合的 Position 对象的市场价值和Bond

其中每个都有一个 getMarketValue 方法被调用(实际上生成数字答案),具体取决于它们继承的 getter getAssetType 告诉我它们的资产类型是什么。

getPortfolioValue 在Portfolio.hpp 中定义,并在Position.hpp 中实现(由于前向声明),但会出现各种“不完整类型”错误。有问题的部分在倒数第二个代码的底部 (Position.hpp)。

我已尝试提供最干净的 MWE。有人知道如何使这个必须跨越> 2个头文件的getPortfolioValue方法工作吗?非常感谢您。

错误图片:

这是我的代码:

Assets.hpp

#ifndef Assets_hpp
#define Assets_hpp
#include <stdio.h>
#include <fstream>
#include <string>
#include <cmath>

#include "Position.hpp"
#include "Portfolio.hpp"

using namespace std;


class Asset{
private:
    string assetType;
    double currentPrice;
    string securityIssuer;
    string securitySymbol;

public:
    Asset(const string& a = "n/a", const double& b = 0.0, const string& c = "n/a", const string& d = "n/a") :
    assetType(a), currentPrice(b), securityIssuer(c), securitySymbol(d)
    {
    };

    virtual string getAssetType();
    virtual double getMarketValue(const int& n);

    virtual ~Asset() {};

};

class Equity: public Asset{
public:

    Equity(const string& a = "EQUITY", const double& b = 0.0, const string& c = "n/a", const string& d = "n/a") :
    Asset(a, b, c, d) 
    {                       
    }:

    virtual string getAssetType(); //Virtual version of Asset's getAssetType
    virtual double getMarketValue(const int& n);


};

class Preferred: public Equity {
public:
    Preferred(const string& a = "PFD", const double& b = 0.0, const string& c = "n/a", const string& d = "n/a") :
    Equity(a, b, c, d)
    {
    };

    virtual double getMarketValue(const int& n);
};


class bond: public Asset{
private:
    double coupon_rate;
    double coupon_freq;
    double par;

public:
    bond(const string& a = "BOND", const double& b = 0.0, const string& c = "n/a", const string& d = "n/a", double e = 0.0, double f = 0.0, double g = 0.0) :
    Asset(a, b, c, d), coupon_rate(e), coupon_freq(f), par(g)
    {
    };

    double bond_value(int num_bonds);

    virtual string getAssetType(); //Virtual version of Asset's getAssetType
    virtual double getMarketValue(const int& n);

};

#endif /* Assets_hpp */

资产.cpp

#include "Assets.hpp"

string Asset::getAssetType() {
    return assetType;
}


string Equity::getAssetType() { //Virtual implementation for Equity.
    return "EQUITY";
}


string bond::getAssetType() { //Virtual implementation for bond.
    return "BOND";
}

Position.hpp

#ifndef Position_hpp
#define Position_hpp
#include <stdio.h>
#include <fstream>
#include <cmath>
#include <string>
#include "Portfolio.hpp"

using namespace std;

class Asset;

class Position{
private:
    Asset* base;
    int position_size;
    double cost_basis;
    double position_age;

public:
    Position(Asset* a, const int& b = 0.0, const double& c = 0.0,
             const double& d = 0.0) :
    base(a), position_size(b), cost_basis(c), position_age(d)              
    {                                                                      
    };

    Asset* getAssetBase() { return base;}      //Getter
    void setAssetBase(Asset* b) { base = b;}   //Setter

};

//  ****************PROBLEM RIGHT BELOW HERE********************************

inline double Portfolio::getPortfolioValue(const int& n) {
if (position->getAssetBase()->getAssetType() == "EQUITY") {
    return position->getAssetBase()->getMarketValue(const int& n);
}

else if (position->getAssetBase()->getAssetType() == "PREFERRED") {
    return position->getAssetBase()->getMarketValue(const int& n);
}

else if (position->getAssetBase()->getAssetType() == "BOND"){
    return position->getAssetBase()->getMarketValue(const int& n);
    }
}
#endif /* Position_hpp */

Portfolio.hpp

#ifndef Portfolio_hpp
#define Portfolio_hpp
#include <stdio.h>
#include <fstream>
#include <string>
#include <cmath>

class Position;

class Portfolio {
private:
    Position* position;
    int num_positions;

public:
    Portfolio(Position* a, const int& b) : position(a), num_positions(b)
    {
    };

    Portfolio(const Portfolio&);

    Position* getPosition() { return position;}     //Getter

    double getPortfolioValue(const int& n); //Both of these implemented in Position header.
    double PortolioCostBasis();


};

#endif /* Portfolio_hpp */

【问题讨论】:

  • 你为什么有那些 if 语句,继承的重点是避免这种情况。
  • 那些 if 语句可能确实是不必要的,但我不确定我该怎么做。 return-> ... 代码位也返回相同的错误,即使我以某种方式摆脱了 if 语句。
  • 您的包含看起来很奇怪。 “Assets.hpp”对“Position.hpp”和“Portfolio.hpp”没有依赖关系,因此应该删除它们。此外,Position 类对Portfolio 没有依赖关系,因此应从“Position.hpp”中删除包含。将Portfolio::getPortfolioValue()的定义放到它所属的“Portfolio.hpp”中。在“Portfolio.hpp”中只包含“Position.hpp”,这是它唯一的依赖项。
  • 附带说明,using namespace std; 是不好的做法,using it in a header file is just completely wrong
  • @zett42 如果您需要我的推理,我在使用前向声明时接受了最佳答案的建议。 stackoverflow.com/questions/8526819/…希望对您有所帮助。

标签: c++ class c++11 inner-classes forward-declaration


【解决方案1】:

您的包含不是基于类的依赖关系,这是主要问题的来源。

"Assets.hpp" 中删除这些行,因为类 AssetEquityPreferredbond 不依赖于 PositionPortfolio

#include "Position.hpp"
#include "Portfolio.hpp"

这里有语法错误(去掉“:”,在类似函数后面也去掉“;”):

Asset(a, b, c, d) 
{                       
}:

“Position.hpp”中删除这一行,因为Position不依赖于Portfolio

#include "Portfolio.hpp"

还将Portfolio::getPortfolioValue 的定义移动到它所属的“Portfolio.hpp”中:

class Portfolio {
public:
    double getPortfolioValue(const int& n) {
        if (position->getAssetBase()->getAssetType() == "EQUITY") {
            return position->getAssetBase()->getMarketValue(const int& n);
        }

        else if (position->getAssetBase()->getAssetType() == "PREFERRED") {
            return position->getAssetBase()->getMarketValue(const int& n);
        }

        else if (position->getAssetBase()->getAssetType() == "BOND"){
            return position->getAssetBase()->getMarketValue(const int& n);
        }
    }
    /* other stuff omitted for brevity */
};

现在您的Portfolio 类依赖于PositionAsset,因此您必须在"Portfolio.hpp" 中包含它们的标题:

#include "Position.hpp"
#include "Assets.hpp"

同时从 "Portfolio.hpp" 中删除前向声明:

class Position;

当您调用Position 的方法时,前向声明是没有用的。您需要完整的声明。

这应该可以修复编译错误。

为什么你在getPortfolioValue() 中有这些ifs 仍然很奇怪。您在所有这些分支中都在做同样的事情......

【讨论】:

  • 我已经采纳了您的建议(是的,我的 if 语句也是不必要的)并实施了它,但现在我遇到了一个更奇怪的错误。 imgur.com/a/pSvHV这是什么意思?
  • @Coolio2654 你还没有实现getMarketValue()
  • 您的建议帮助我很好地解决了这个问题。我可以看到,我在前向声明上绊倒了自己,而事实上它们还不够,并且使用变通方法让它们工作,给我已经相当大的代码增加了更容易出错的复杂性。感谢您指出我的简单错误。
【解决方案2】:

问题是您需要使用if(position-&gt;getAssetBase()-&gt;getAssetType() == "Equity") 而不是if(position-&gt;getAssetBase()-&gt;getAssetType()= "Equity")

希望这会有所帮助。

【讨论】:

  • 您好,我修复了这个幼稚的错误,感谢您的发现,但我的根本问题仍然存在。
  • 而我的仓位只是一个仓位对象,基本上我拥有多少资产以及持有多长时间。从某种意义上说,投资组合只是持有多个职位。
  • @Coolio2654 我看不到任何错误,您可以添加错误
【解决方案3】:

演示问题的内联方法取决于asset.h 中的定义,但您在定义问题函数时并未包含asset.h。我不确定在问题函数之前是否仅包含asset.h 是否可以解决问题(这里可能存在我没有看到的循环依赖关系)。

【讨论】:

  • 我在顶部的 Assets 标头中包含了后两个标头,并在后两个标头中前向声明了必要的类。我知道这种方法适用于简单的前向声明,但似乎不适用于我更复杂的使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-07
  • 1970-01-01
  • 1970-01-01
  • 2013-09-06
  • 1970-01-01
  • 1970-01-01
  • 2011-10-17
相关资源
最近更新 更多