2014-09-26 24 views
2

假設我有這樣的代碼全部設置:操作在複合材料的設計模式在重載C++

class Function 
{ 
public: 
    virtual double eval(double x) const =0; 
}; 

class Polynomial : public Function 
{ 
private: 
    std::vector<double> coefficients; 
public: 
    // ... 
}; 

class CompositeFunction : public Function 
{ 
private: 
    char operation; 
    Function* left; 
    Function* right; 
public: 
    // ... 
}; 

CompositeFunction operator+(Function& f, Function& g) { 
    return CompositeFunction('+',&f,&g); 
} 

現在,我嘗試做以下事情:

CompositeFunction f = Polynomial({1,2}) + Polynomial({3,2}); 
printf("%lf\n",f.eval(1)); 

我不得到任何編譯錯誤,但是當我嘗試評估f時,Valgrind告訴我我正在處理不良數據。我總是得到正確的答案,但是這讓我感到困惑。 我試圖停止使用堆棧分配的參數,但我不能重載任何指針操作。 這些類的用戶有沒有無指針的方法或友好的?

回答

0

這是因爲f引用了兩個臨時對象。

展開出來,以使其更明顯:

CompositeFunction f = operator+(Polynomial({1,2}), Polynomial({3,2})); 

第f保存由多項式({1,2})和多項式創建的臨時對象的引用({3,2})。

你可能要考慮使用std::function<double(double)>對象和lambda表達式,像這樣:

#include <iostream> 
#include <functional> 
#include <vector> 

typedef std::function<double(double)> Function; 

Function polynomial(std::vector<double> const &coefficients) { 
    return [coefficients](double x) { 
     return x * coefficients[0]; // dummy evaluation 
    }; 
} 

Function add(Function f1, Function f2) { 
    return [f1, f2](double x) { return f1(x) + f2(x); }; 
} 

int main() { 
    Function f = add(polynomial({3,4}), polynomial({1,2})); 
    std::cout << f(3.3) << std::endl; 
} 

這是用的std :: shared_ptr的:

#include <iostream> 
#include <functional> 
#include <memory> 
#include <vector> 

class Function 
{ 
public: 
    virtual double eval(double x) const = 0; 
    virtual double derivative(double x) const = 0; 
    virtual ~Function() {} 
}; 
typedef std::shared_ptr<Function> FunctionPtr; 

class Polynomial : public Function 
{ 
private: 
    std::vector<double> coefficients; 
public: 
    // ... 
    Polynomial(std::vector<double> c) : coefficients(c) {} 
}; 

class CompositeFunction : public Function 
{ 
private: 
    char operation; 
    FunctionPtr left; 
    FunctionPtr right; 
public: 
    // ... 
    CompositeFunction(FunctionPtr l, FunctionPtr r) : operation('+'), left(l), right(r) {} 
}; 

FunctionPtr operator+(FunctionPtr f, FunctionPtr g) { 
    return std::make_shared<CompositeFunction>(f, g); 
} 

int main() { 
    auto p1 = std::make_shared<Polynomial>(std::vector<double>{1.0, 2.0}); 
    auto p2 = std::make_shared<Polynomial>(std::vector<double>{3.0, 4.0}); 
    auto f = std::make_shared<CompositeFunction>(p1, p2); 
    auto f2 = p1 + p2; 
    std::cout << f2->eval(3.3) << std::endl; 
    std::cout << f2->derivative(3.3) << std::endl; 
} 
+0

是啊,我已經注意到了這一點。試圖複製他們,但我不能訪問他們的複製構造函數,因爲他們現在是函數。 也許增加一個複製功能到接口是一個好主意? – danisson 2014-09-26 00:44:28

+0

如果您使用std :: function對象,則可以按值傳遞它們。 – walrii 2014-09-26 00:45:22

+0

我不知道'std :: function',它看起來很酷。然而,評估這些函數並不是我唯一關心的事情,評估它們的衍生物也非常重要,這可以通過樹結構和對「基本」函數的衍生物的評估輕鬆完成。 這就是我決定「重新發明輪子」的主要原因 – danisson 2014-09-26 00:58:51