1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

PythonistaのためのC++記法入門: それC++ではどう書くの6 ~関数定義1~

Posted at

PythonistaのためのC++記法入門: それC++ではどう書くの5の続き。今回からは関数について。

関数関連

関数の基本

例として

  1. 整数型の2値を受け取ってその和(整数型)を返す関数
  2. 整数型の2値を受け取ってその平均(整数型とは限らない)を返す関数
    を考える。

Pythonではこう書いた

def sum(x, y):
    ans = x + y
    return ans

def average(x, y):
    ans = sum(x, y) / 2.
    return ans

def main():
    a = 10
    b = 20
    print(sum(a, b))  # 30 が出力される
    print(average(a, b))  # 15.0 が出力される

if __name__ == '__main__':
    main()

Pythonでは引数の型も、返り値の型も何も気にしなくてよい。その代わり、この場合だと引数や返り値の型が狙い通りになるか確証はない。

C++ではこう書く

#include <bits/stdc++.h>
using namespace std;

int sum(int a, int b) {
  int ans;
  ans = a + b;
  return ans;
}

float average(int a, int b) {
  float ans;
  ans = sum(a, b) / 2.;
  return ans;
}

int main()
{
  int a = 10;
  int b = 20;
  cout << sum(a, b) << endl;  // 30 が出力される
  cout << average(a, b) << endl;  // 15 が出力される(表記上int型に見えるがtypeidはf,つまりfloat型)
}

一方C++では引数や返り値の型を考慮した上で関数を定義する必要がある。
整数型の2値の平均は常に整数型になるとは限らないため、floatを返り値に取るように関数を定義しないと所望の答えが得られない。

(一応)Pythonでもこう書ける

Python3.5以降で導入された型ヒントを用いることで型を考慮した関数定義ができるようになった。スクリプトが複雑化し、どの関数がどういった意味を持ち、何を引数に取って何を返すべきかがわかりにくくなってきたときに地味に便利である。

def sum(x: int, y: int) -> int:
    ans = x + y
    return ans

def average(x: int, y: int) -> float:
    ans = sum(x, y) / 2.
    return ans

返り値がない関数

PythonでもC++でもreturn文を省略できるのは同じ。

Pythonではこう書いた

def display_string(x):
    print(x)

def main():
    display_string("This will be displayed.")

if __name__ == '__main__':
    main()

実質的にNoneを返している。型ヒントを使う場合はdef func(x) -> None:と書く。

C++ではこう書く

#include <bits/stdc++.h>
using namespace std;

void display_string(string x) {
    cout << x << endl;
}

int main()
{
  display_string("This will be displayed.");  // This will be displayed. と出力される
}

C++では関数定義時に返り値の情報が必要なので、このような場合はvoidを充てる(個人的にこのワードチョイスは絶妙だと思う)。

デフォルト値を指定する

Pythonではこう書いた

def greet(message, name="John", goal=1):
    print(message, end=" ")
    print(f"My name is {name}. I want to be No.{goal}.")

def main():
    greet("Yeah!!!")
    greet("Hi.", "Mike")
    greet("Well...", "Bob", 2)

if __name__ == '__main__':
    main()
#include <bits/stdc++.h>
using namespace std;

void greet(string message, string name="John", int goal=1) {
    cout << message;
    cout << " My name is " << name << ". I want to be No." << goal << "." << endl;
}

int main() {
    greet("Yeah!!!");
    greet("Hi.", "Mike");
    greet("Well...", "Bob", 2);
}

ほとんど書き方や使い方は同じ。出力はいずれも以下のようになる。

Yeah!!! My name is John. I want to be No.1.
Hi. My name is Mike. I want to be No.1.
Well... My name is Bob. I want to be No.2.

オーバーロード(overload)

C++ではこう書く

C++では同名の関数を定義できる。これはPythonでは(異なる名前空間を用いない限りは)できない。
オーバーロードによる多重定義ができる関数は、「引数の型」か「引数の数」が異なる場合である。
よって、以下のように二つのsum関数を用意することができる(意義は薄い)。

int sum(int a, int b){
  int ans;
  ans = a + b;
  return ans;
}

int sum(int a, int b, int c){
  int ans;
  ans = a + b + c;
  return ans;
}

ラムダ式

Pythonではこう書いた

my_min = lambda x, y: x if x < y else y

すなわち

関数名 = lambda 引数1, 引数2, ...: 処理

C++ではこう書く

auto my_min = [](int a, int b) {
  int answer= a < b ? a : b;
  return answer;
};

すなわち

auto 関数名 = [](引数1の型 引数1, 引数2の型 引数2, ...) {
  処理;
  return 返り値;
};
1
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?