• 締切済み

C++でクラスの自己診断を効率良く行うには?

JavaやPythonで用いる事が可能なクラスの自己診断をC++で効率良く書くにはどうすればよいか、教えて頂けますか。 例えばカウンターを表すクラスCounterをJavaで書くと、 public class Counter { // ここにメンバー変数やメンバー関数の定義を置く public static void main(String args[]){ # 自己診断コード Counter ct = new Counter(); ct.count_up(); System.out.println(ct.get_count()); } } となると思います。このモジュールをそのまま実行すれば、自己診断コードが実行されますし、外部からこのモジュールを呼び出す場合は自己診断コードが呼び出されないようになるので、大変便利です。 Pythonの場合は、if __name__ == "__main__":の下に自己診断コードを置くと言うことがよく行われます。 このような自己診断をC++で効率良く実現するにはどうすればいいのでしょうか。 今考えている方法は、 // Counter.h class Counter { private: int counter; public: Counter(); void count_up(); int get_count(); }; // Counter.C #undef MAIN #include "Counter.h" using namespace std; // メンバー関数の定義をここに置く #ifdef MAIN int main(){ Counter ct; ct.count_up(); cout << ct.get_count() << endl; return 0; } #endif のように書く事ですが、自己診断・外部からの使用を切り替えるたびに#define MAIN <-> #undef MAINの書き換えを行わなければならず、少々不便です。 よろしくお願いします。

みんなの回答

  • rabbit_cat
  • ベストアンサー率40% (829/2062)
回答No.2

#1さんみたいな方法でいいと思いますが、本当にまじめにやりたいなら、CppUnitみたいなフレームワークを使って、1つクラスを作るごとに、それに対応するテスト用のクラスを作るってのが本当かな。

Mephyl
質問者

お礼

ご回答ありがとうございます。 当方はCppUnitに関しては全くの無知でしたが、WEBで検索すると沢山ヒットしました。

回答No.1

class Counter {  .... }; #ifdef TEST int main() {  テストコード } #endif としておくだけじゃないですか? コンパイル時にオプション: -DTEST を付ければ main が生成されるんだから。

Mephyl
質問者

お礼

ご回答ありがとうございます。 -Dオプションの存在および動作を確認することができました。

関連するQ&A

  • Java クラスを使ったソート

    Javaで隣接交換法を用いて配列dataを昇順に並び替え、出力するプログラムを作成する。 ただし、ループ処理には、int型の変数は使わず、以下のCounterクラスを使用する。 という課題が出て、とり組んでみたのですが所々よく分からないので、お力添えしていただければと思います。 課題には下記のような条件が書いてありました。 配列data={54,76,32,89,45,11,8,54,29,67}; [クラス] Counter [インスタンス変数] int型の値を保持するcount [コンストラクタ] 引数で渡された値を初期値としてインスタンス変数に設定する。 引数を省略された場合、ゼロを設定する。 [メソッド] increment 値に1加算する decrement 値に1減算する compareTo 以下の処理を行う Counterの保持している値が引数に指定された値と 等しい場合、値0を返す。 Counterの保持している値が引数に指定された値より 小さい場合、0より小さい値を返す。 Counterの保持している値が引数に指定された値より 大きい場合、0より大きい値を返す。 get Counterの保持している値を添え字として、 引数で渡された配列の要素を取得します。 set Counterの保持している値を添え字として、 第1引数で渡された配列に第2引数で渡された値を設定します。 以下組んだものです。 ---- class Counter { int count = 0; Counter(int count) { this.count = count; } Counter() { this.count = 0; } public int get(int[] data) { return this.count; } public void set(int[] data, int count) { this.count = count; } public void increment() { this.count = count + 1; } public void decrement() { this.count = count - 1; } public int compareTo() { return count; } } public class Lesson09 { public static void main(String args[]) { Counter counter = new Counter(0); int[] data = {54, 76, 32, 89, 45, 11, 8, 54, 67}; counter.get(data); counter.set(data, 0); } } ---- とりあえず、compareToとsetとgetの部分をどう記述していいのかがよく分かりません。 よろしくお願いします。

    • ベストアンサー
    • Java
  • C++ クラスをメンバにもつクラスについて

    お世話になります。C++初心者でうまくコードが書けません(><) クラス1と2があり、クラス1のメンバにはクラス2があります。 メインでクラス1をインスタンス化してクラス2のfunc2を呼び出します。 func2ではクラス1のインスタンスから呼び出された場合にクラス1の m_int1を取得します。 Class Class1{ public:  int m_int1;  Class2 m_Class2; }; Class Class2{ public: void func2(); }; void Class2::func2(){  /*ここの記述方法が分かりません*/  /*C1から呼び出されたらC1のm_int1に100を入れる*/  /*以下間違え*/  class1 C2_1;/*別のclass1のオブジェクトなのでこれに入れてもダメっぽい*/  C2_1.m_int1 = 100; } void main(){  class1 C1;  C1.m_int1 = 10;  C1.m_class2.func(); } C1.m_class2.func()の中から呼び出したC1にアクセスする方法が 分かりません(TT)。実体がまだあるのだからアクセスする方法は あると思うのですが・・・ どなたかよろしくお願いします。

  • C#でクラス継承について

    下記のようなコードは、可能なのでしょうか? // クラス定義 abstract class Base { int a; Public int A { get{ return a; } } } class Sub1 : Base { int b; public int B { set { b = value; } } }; class Sub2 : Base { // 中略 } static class Program { [STAThread] static void Main(string [] args) { Base aaa = new Sub1(); Base bbb = new Sub2(); func(aaa); // ここでCS1502, CS1503 func(bbb); // ここでCS1502, CS1503 } void func(Sub1 _aaa) { // 中略 } void func(Sub2 _bbb) { // 中略 } } コメントに書いたとおり、CS1502(引数が合わない)が出ます。 func((Sub1)aaa); の様にキャストしないと、動作させることは難しいでしょうか? ※ 実際のコードでは、func(aaa), func(bbb)の呼び出し部分をループでまわしたいと考えています。

  • c++,ある関数のクラスから別のクラスの関数を呼ぶ

    c++で、あるクラスのメンバ関数から、別のクラスのメンバ関すを呼びたいのですが、どのようにしたらできますか? 例えば、以下のような単純なコードを考えています。やりたいことは、Aのメンバ関数であるaaa()からBのクラスであるbbb()を呼びたいと思っています。その理由を少し説明します。ここでは、Aというクラスとmain関数はオープンソースコードを例えています。できるだけ、元のオープンソースコードを書き換えずに新たな機能を拡張したいと思っています。そこで、Bというクラスを使って、元のオープンソースコードに機能を拡張しようとしています。このような理由なので、bbb()という関数はaaa()という関数から呼びたいです。メイン関数には何も書き加えないのがベストです。 現状では、実行すると「this is aaa」という出力しか出ません。ここに「this is bbb」の出力を加えたいです。クラスAとBにある程度コマンドを追加して、解決できないでしょうか。 #include <iostream> using namespace std; //------------------------------------------------------ class A{ public: void aaa(); virtual void bbb(){} }; //------------------------------------------------------ //------------------------------------------------------ class B : public A{ public: void bbb(); }; //------------------------------------------------------ //------------------------------------------------------ void A::aaa() { cout << "this is aaa \n"; bbb(); } //------------------------------------------------------ //------------------------------------------------------ void B::bbb() { cout << "this is bbb \n"; } //------------------------------------------------------ //------------------------------------------------------ int main() { A a; a.aaa(); return 0; } //------------------------------------------------------

  • C言語 

    #include <stdio.h> int main(void) { int ch; int count = 1; while( (ch = getchar()) != EOF) { if(ch == '\n') count++; } printf("行数は%dです。", count); return(0); } このコードの if(ch == '\n') count++; の部分がわかりません。 aを入力したとしてchにaが入っても、a=='\n'にはならないと思うのですが、実行して見ると行数がカウントされます。 (ch=='\n')というのはchと改行が同じなら行数を1増やすと言う事になると思うのですがよくわかりません。 教えてくださいm(_ _ )m

  • C++ クラスの作り方

    Windows10の上で、Visual Studio Community2015 を使ってC++を勉強中の者です。 Time クラスというのを定義して使おうとしましたが、クライアント側のプログラム作成中にエラーメッセージが出てきて、色々考えましたがどこが悪いのかわかりません。 プログラム自体は時刻を設定してそれを表示させるだけのものです。 詳しい方がいらっしゃいましたら、ご教授お願い致します。 問題のエラーメッセージ; "consoleApplication69.cpp" を作成中にエディターの中で、波型の赤線が出ているところにカーソルを持っていくと、次の3か所でそれぞれ次のようなエラーメッセージが出てきます。 (1) #include "time3.h" のところ: 「ソースファイルをひらけません。"time3.h"」 (2) 関数 incrementMinute( )のプロトタイプのところ:「不完全な型は使用できません。」 (3) 最初のパラメーター Time & のところ:「識別子 Time が定義されていません。」 以下に、 1: 私が作ったTimeクラスの定義のあるヘッダー "time3.h", 2: メンバー関数の定義ファイル "time3.cpp" 3:クライアント側プログラム "consoleApplication69.cpp" の3つのソースコードをコピーします。 "time3.cpp" については長いので、上の半分だけにしました。 ****************************************************** 1: "time3.h" ******************************************************** #pragma once // header file for Time class // time3.h #ifndef TIME3_H #define TIME3_H class Time { public: Time(int = 0, int = 0, int = 0); ~Time(); void setTime(int, int, int); void setHour(int); void setMinute(int); void setSecond(int); int getHour(); int getMinute(); int getSecond(); void printUniversal(); void printStandard(); private: int hour; int minute; int second; }; #endif *********************************************** 2: "time3.cpp" ************************************************ #include <iostream> #include <iomanip> #include <cstdlib> #include <ctime> #include <cmath> #include <cstring> #include "time3.h" using namespace System; using namespace std; Time::Time(int hr, int min, int sec) { setTime(hr, min, sec); } void Time::setTime(int hr, int min, int sec) { setHour(hr); setMinute(min); setSecond(sec); } void Time::setHour(int hr) { hour = (0 <= hr && hr <= 23) ? hr : 0; } void Time::setMinute(int min) { minute = (0 <= min && min <= 59) ? min : 0; } void Time::setSecond(int sec) { second = (0 <= sec && sec <= 59) ? sec : 0; } ********************************************************* 3: "consoleApplication69.cpp" ********************************************************* // ConsoleApplication69.cpp : メイン プロジェクト ファイルです。 #include "stdafx.h" #include <iostream> #include <iomanip> #include "time3.h" using namespace System; using namespace std; //prototype void incrementMinute(Time &, const int); int main() { Time t; t.setHour(2); t.setMinute(10); t.setSecond(30); cout << " current time is "; cout << setfill('0'); cout << setw(2) << t.getHour() << ":"; cout << setw(2) << t.getMinute() << ":"; cout << setw(2) << t.getSecond() << "\n"; return 0; } // function void incrementMinute(Time &tt, const int num) { // まだ未定義 } またソリューションエクスプローラーの画面写真も添付します。 ヘッダーファイルもインクルードしていますし、ソリューションの中に入れたつもりですが、なぜ Time が定義されていないといわれるのでしょうか? どうぞよろしくお願いいたします。

  • C++基底クラスに戻り値の異なる関数が宣言されている場合

    こんにちは。 質問させてください。 以下のようなコードがあったとします。 class Base1 { public:   virtual int get()=0; }; class Base2 { public:   virtual float get()=0; }; class Ex : public Base1, public Base2 { public:   int get(){return 0;}   float get(){return 0.0f;} }; void main() { } このプログラムをコンパイルすると 「'Ex::get': オーバーライドする仮想関数の戻り値の型が異なり、'Base1::get' の covariant ではありません。」 というエラーが出てしまいます。 関数の名前と引数が同じで戻り値だけが異なる場合はエラーが出るのはわかるのですが、基底クラスのBase1、Base2は変更不可能だとするとどのように回避すればいいのでしょうか? よろしくお願いします。 /*   WindowsXP Professional SP3   VisualStudio2005 AcademicEdition */

  • javaのカウントアップについて

    javaのEclipseを使っています。 カウントアップ後、表示する度に、 1, 2, 3, …と表示するプログラムを作りたいです。 プログラム例を教えて下さい。 public class Test { public static void main(String[] args) { Count count = new Count(); int scount = count.read(); count.write(scount); } } class Count { int count = 1; int read() { return count++; } void write(int scount) { System.out.println(scount); } }

  • C言語 外部変数について

    #include<stdio.h> int count; int f(int x){  int i;  for(i=0 ; x < 10 ; i++){   x*=2;   count++;   }  return x; } int main(void){  count=0;  printf("%d %d",f(1),count);  return 0; } のようなプログラムを作って実行してみたところ f(1)の部分は1024と自分の目的通りの結果が返ってきましたが countの部分が0とでてきてしましました 関数内で10回の繰り返しを行ったので 10がはいってると思ったのですが どこを直せば10の値がでてきますか?

  • Cの変数の初期化のタイミングについて

    以下のようなCの演習プログラムについてお尋ねします。 やっていることは、inc_counterと言う関数を呼び出して呼び出すたびに変数を1つづつ増やすというもので、10回呼び出すので変数が10になるというものです。この演習プログラムが言いたいことは変数counterの動作ということです。 externですべての関数の外側で宣言されているから呼び出す側、呼び出される側で共通になっているということですが、void inc_couter(void)の実体(後方)の前にint counter=0;となっています。この文は変数counterの初期化ということだと思いますが、これが実行されるのはいつなのでしょうか。関数inc_counerの呼び出しのときは実行されないのでしょうか。もしそうなら関数が呼び出されるたびに初期化されるはずですが、そうではないのでしょうか。 変数のスコープとか初期化とかの問題だと思いますが、この辺を間違って理解すると大けがをしそうなのでお尋ねします。よろしくお願いします。 #include<stdio.h> extern int counter; void inc_counter(void); main() { int index; for(index=0; index<10; index++) inc_counter(); (void) printf("Counter is %d\n",counter); return (0); } int counter=0; void inc_counter(void) { counter++; }