2016-08-01 5 views
0

Ich bin ein Anfänger in C++ und möchte ein einfaches Beispiel für Composite-Funktion zu tun. Zum Beispiel in MATLAB, kann ich schreibenComposite-Funktion in C++

a = @(x) 2*x 
b = @(y) 3*y 
a(b(1)) 

Antwort ist 6

ich folgende Fragen gesucht. function composition in C++/C++11 und Function Composition in C++

Aber sie sind erweiterte Funktionen erstellt mit, wie Vorlagen, zu denen ich zu dieser Zeit nicht viel bekannt. Gibt es einen einfachen und direkten Weg, dies zu erreichen? Im obigen MATLAB-Code muss der Benutzer die Implementierung von Funktionskennungen nicht kennen. Der Benutzer kann nur die richtige Syntax verwenden, um das Ergebnis zu erhalten. Gibt es so einen Weg in C++?

** Ein weiterer Edit: **

In obigem Code, ich bin Wert am Ende setzen. Wenn ich das Ergebnis jedoch an eine dritte Funktion übergeben möchte, kann MATLAB es immer noch als Funktion betrachten. Aber wie geht das in C++?

beispielsweise zusätzlich zu obigem Code, betrachten diesen Code:

c = @(p,q) a(p)* b(q) %This results a function 
c(1,2) 
answer=12 

d = @(r) a(b(r)) 
d(1) 
answer=6 

function [ output1 ] = f1(arg1) 
val = 2.0; 
output1 = feval(arg1,val) 
end 

f1(d) 
answer = 12 

In diesem Code c nehmen zwei Funktionen als Eingabe und d zusammengesetzte Funktion ist. Im nächsten Beispiel übernimmt die Funktion f1 eine Funktion als Argument und verwendet die integrierte MATLAB-Funktion feval, um die Funktion unter val auszuwerten.

Wie kann ich dies in C++ erreichen?

+3

Wahrscheinlich etwas ähnliches wie [C++ Lambda-Funktionen] (http://en.cppreference.com/w/cpp/language/lambda)? Was genau macht '@ (x)' in MATLAB? –

+0

Ich verstehe immer noch 'fun1' nicht. Es sieht so aus, als ob es ein Argument "c" braucht, dieses Argument ignoriert und * * * unbedingt zurückgibt. Du nennst dann * 'fun1' nennen und passierst' 1', was ignoriert werden sollte, aber irgendwie lautet die Antwort 2, nicht '@ (x) 2 * x' oder' a'. WTF? – zwol

+0

Funktionszusammensetzung ist eine Operation, die zwei Funktionen übernimmt und eine andere Funktion zurückgibt. Ich sehe keine Funktionszusammensetzung im Matlab-Code, kannst du mir zeigen, wo sie sich versteckt? –

Antwort

4

Ich bin Mißverständnis Ihre Frage vielleicht, aber es klingt einfach:

int a(const int x) { return x * 2; } 
int b(const int y) { return y * 3; } 

std::cout << a(b(1)) << std::endl; 

Ihre neuesten bearbeiten Bezüglich Sie eine Funktion ein Ergebnis einer anderen Funktion zurückkehren machen:

int fun1(const int c) { return a(c); } 

std::cout << fun1(1) << std::endl; 

Beachten Sie, dass Dies liefert eine Nummer, das Ergebnis des Aufrufs a, nicht die Funktion a selbst. Sicher, Sie können einen Zeiger auf diese Funktion zurückgeben, aber dann wäre die Syntax anders: Sie müssten etwas wie schreiben, was ziemlich hässlich und kompliziert ist.

+0

Dies wird nicht kompiliert. –

+0

@ForceBru Danke für die Antwort. Ich habe die Frage bearbeitet. Kannst du dir das mal ansehen? – 34usdh34

2

C++ 's evaluation strategy für Funktionsargumente ist immer "eifrig" und in der Regel "nach Wert". Die kurze Version von dem, was das bedeutet, ist, eine zusammengesetzte Funktion Aufrufsequenz wie

x = a(b(c(1))); 

ist genau die gleiche wie

{ 
    auto t0 = c(1); 
    auto t1 = b(t0); 
    x = a(t1); 
} 

(auto t0 bedeutet „t0 gibt unabhängig von der Art am besten geeignet ist“; Es ist ein relativ neues Feature und funktioniert möglicherweise nicht in Ihrem C++ - Compiler Die geschweiften Klammern zeigen an, dass die temporären Variablen t0 und t1 nach der Zuweisung zu x zerstört werden.)

Ich bringe das auf, weil Sie ständig über Funktionen sprechen, die "Funktionen als Eingabe nehmen". Es sind Programmiersprachen, wie R, wo a(b(1)) Schreiben des Ausdruck passieren würdeb(1)-a, und eigentlich nur Anrufb wenn a für den Ausdruck gebeten, ausgewertet werden. I dachte MATLAB war nicht so, aber ich könnte falsch liegen. Egal, C++ ist definitiv nicht so. In C++ wertet a(b(1)) zuerst b(1) aus und gibt dann das Ergebnis dieser Auswertung an a weiter; a hat keine Möglichkeit herauszufinden, dass das Ergebnis von einem Anruf an b kam. Der nur Fall in C++, der korrekt als "eine Funktion, die eine andere Funktion als Eingabe nimmt" beschrieben wird, würde Ihrem Beispiel entsprechen, das feval verwendet.

Jetzt: Die direkte Übersetzung des MATLAB-Code Sie gezeigt haben, ist

#include <stdio.h> 

static double a(double x)   { return 2*x; } 
static double b(double y)   { return 3*y; } 
static double c(double p, double q) { return a(p) * b(q); } 
static double d(double r)   { return a(b(r)); } 

static double f1(double (*arg1)(double)) 
{ return arg1(2.0); } 

int main() 
{ 
    printf("%g\n", a(b(1))); // prints 6 
    printf("%g\n", c(1,2)); // prints 12 
    printf("%g\n", d(1));  // prints 6 
    printf("%g\n", f1(d)); // prints 12 
    printf("%g\n", f1(a)); // prints 4 
    return 0; 
} 

(C++ hat keine Notwendigkeit für explizite Syntax wie feval, da die eingegebene Parameterdeklaration, double (*arg1)(double) den Compiler sagt, dass arg1(2.0) ist gültig ist. bei älteren Code können Sie (*arg1)(2.0) sehen, aber das ist nicht erforderlich, und ich denke, es ist der Code weniger lesbar macht.)

(I printf in diesem Code verwendet haben, anstelle von C++ 's iostreams, zum Teil, weil ich persönlich denke, printf ist viel ergonomischer als iostreams, und teilweise, weil das macht dieses Programm auch ein gültiges C-Programm mit der gleichen Semantik. Das kann zum Beispiel nützlich sein, wenn Sie C++ lernen, weil Sie MATLAB-Erweiterungen schreiben wollen, was bei der letzten Überprüfung einfacher war, wenn Sie sich an C. erinnerten.

Es gibt signifikante Unterschiede; Zum Beispiel akzeptieren die MATLAB-Funktionen Vektoren, während diese C++ - Funktionen nur einzelne Werte annehmen; wenn ich b wollte, um c zu nennen, hätte ich sie tauschen oder eine "Vorwärtsdeklaration" von c über b schreiben müssen; und in C++ (mit ein paar Ausnahmen, über die Sie sich jetzt keine Gedanken machen müssen) muss Ihr gesamter Code innerhalb der einen oder anderen Funktion liegen. Das Lernen dieser Unterschiede ist Teil des Erlernens von C++, aber Sie müssen sich noch nicht mit Templates und Lambdas und Klassen und so weiter verwirren. Halten Sie sich zunächst an freie Funktionen mit festen Signaturen.

Schließlich möchte ich nachlässig, wenn ich nicht erwähnen, dass in

static double c(double p, double q) { return a(p) * b(q); } 

die Anrufe an a und b in entweder um passieren könnte. Es ist die Rede davon, dies zu ändern, aber es ist noch nicht geschehen.

+0

'std :: printf'? Ja wirklich?!? Sogar das OP verwendete 'std :: cout'. –

+0

@NikBougalis Ich glaube, ich habe meine Meinung über Iostreams ziemlich klar gemacht ;-) – zwol

+0

Danke für die Antwort. Ich habe die Frage bearbeitet. Kannst du dir das mal ansehen? – 34usdh34

4

Wie wäre:

#include <iostream> 

int main(int, char**) 
{ 
    auto a = [](int x) { return 2 * x; }; 
    auto b = [](int y) { return 3 * y; }; 

    for (int i = 0; i < 5; ++i) 
     std::cout << i << " -> " << a(b(i)) << std::endl; 

    return 0; 
} 
+0

Das hatte ich mir vorgenommen. Sieht dem MATLAB-Code am ähnlichsten und ist inline. –

+0

Danke für die Antwort. Ich habe die Frage bearbeitet. Kannst du dir das mal ansehen? – 34usdh34

+0

Sie können beliebig viele Lambdas erstellen und verketten. –

0
int a(const int x){return x * 2;} 
int b(const int x){return x * 3;} 
int fun1(const int x){return a(x);} 

std::cout << fun1(1) << std::endl; //returns 2 

Dies ist eine grundlegende Kompilierung-Zusammensetzung. Wenn Sie eine Laufzeitkomposition wollten, werden die Dinge etwas komplizierter.