varクラスつくったよ!

アバター
MoNoQLoREATOR
記事: 284
登録日時: 14年前
住所: 東京

varクラスつくったよ!

投稿記事 by MoNoQLoREATOR » 13年前

一部修整しました。ここをクリックしてください

varクラスと言うだけで、おそらくどんなクラスなのか想像がつくと思います。
そうです。javascriptのように数値と文字列をあまり考えずに扱うことができるクラスです。ただ、javascriptでは数値を指しているのか文字列を指しているのかが曖昧(特に連結時)という欠点があったので、そこはカバーしました。

使用例です。クリックしてご覧ください
► スポイラーを表示

最後に
このクラスは関数の引数の型として使用された際に最大の効果を発揮すると思います。
その関数を利用する際に渡す変数が数値か文字列かを気にする必要がないからです。
あとは、コンストではないchar*型ポインタを渡せることですかね。これは大きいと思います。
これでプログラミング速度がそれなりに上がるのではないかと思います。
それでは良いプログラミングライフを。
最後に編集したユーザー MoNoQLoREATOR on 2011年11月08日(火) 22:35 [ 編集 1 回目 ]

naohiro19
記事: 256
登録日時: 14年前

Re: varクラスつくったよ!

投稿記事 by naohiro19 » 13年前

Visual Studio 2010で正常にビルドができることを確認しました。

taketoshi
記事: 222
登録日時: 14年前

Re: varクラスつくったよ!

投稿記事 by taketoshi » 13年前

お、スゲェ。
まだ知識が浅くて全ては読み解けませんが
標準のクラスを親クラスとして、派生クラスを作ることが可能なんですね

この書き方、知らなかったし想像もしませんでした。。。。

アバター
MoNoQLoREATOR
記事: 284
登録日時: 14年前
住所: 東京

Re: varクラスつくったよ!

投稿記事 by MoNoQLoREATOR » 13年前

>>naohiro19さん
確認ありがとうございます。

>>taketoshiさん
そうなんです。
派生というルールを使えば標準のクラスを自分好みに書き換えることが簡単にできるのです!
楽しいですよ^^

アバター
tk-xleader
記事: 158
登録日時: 14年前

Re: varクラスつくったよ!

投稿記事 by tk-xleader » 13年前

stringやvectorなどは継承してもいいのですが、public継承だけはやめたほうがいいです。これらのクラスのデストラクタは、virtualではないからです。
やるとしたら、protected or private継承で、使うメンバ関数だけusing宣言をしてpublicにするのが一番いいです。

参考:protected敬称の使い方 - Life like a clown

アバター
GRAM
記事: 164
登録日時: 14年前

Re: varクラスつくったよ!

投稿記事 by GRAM » 13年前

面白いと思いました。
そういえばスクリプトって最近使っていないので忘れていましたがそんなような性質がありましたね。
むかし「便利だけど、便利だからこうなっているのか、それともその他の事情でこうなっているのかどっちだろう?」と悩んだことがあります。

>>tkmakwins15さん
public継承がまずいということは自分も思ったのですが質問させてください。
このコードの場合、そもそも継承が必要なのか?というのが自分の考えです。
private継承やprotected継承を使うとして、この場合のそのメリットはなんでしょうか?
基底クラスの使用法見る限り、単純なコンポジットでいいようにも思えるのです。
そのあたりを教えていただくと個人的に勉強になりますw

アバター
MoNoQLoREATOR
記事: 284
登録日時: 14年前
住所: 東京

Re: varクラスつくったよ!

投稿記事 by MoNoQLoREATOR » 13年前

>>そもそも継承が必要なのか?
答えはずばりNOです。
継承する方法が一番簡単だったからです。
いえ、むしろ継承する以外の方法では作成できなかったからです。
stringに自動型変換機能のようなものがついたら更に便利になるなと思って作ったので、stringの機能は全て今まで通り使うことができる必要があります。私はstringの機能を全て把握しているわけではないので、継承以外の方法では不可能でした。

コンポジットという言葉も初めて聞きました。それと、継承する方法は
class 名前 :public 継承するクラス名
とするのだと習っただけで、それ以外の方法は知りませんでした。

最後に、基底クラスのデストラクタがバーチャルでないことで、どのような問題が起きるのでしょうか?

アバター
MoNoQLoREATOR
記事: 284
登録日時: 14年前
住所: 東京

Re: varクラスつくったよ!

投稿記事 by MoNoQLoREATOR » 13年前

>>最後に、基底クラスのデストラクタがバーチャルでないことで、どのような問題が起きるのでしょうか?
すみません。教えていただいた解説サイトに載っていました。
しかしこれは基底クラスのデストラクタがバーチャルではない所が悪いのではなく、単純に基底クラスのポインタでdeletできてしまう所が悪いのですから、素直にそう言えばよかったのではないかと思いますが、それ以外に何か都合の悪いことでもあるのでしょうか?

アバター
GRAM
記事: 164
登録日時: 14年前

RE: varクラスつくったよ!

投稿記事 by GRAM » 13年前

デストラクタ云々はもちろんですが、public継承はいろいろ面倒です。

CODE:

using namespace std;
 
int main(){
    var v = 200;
    v += "100";
    cout << v.numcc() << endl;
    cout << v.c_str() << endl;
    cout << v << endl; //さてどっちでしょう?
    string& s = v;
    s += "100";
        
    cout << v.numcc() << endl; //アップキャストできるのが悪い
    cout << v.c_str() << endl;
 
}
そもそもの話でアップキャストができてしまうと面倒ですよ。
少なくともprivate等の継承を使えばこの手の問題は避けられます。
継承を使わなくてもこの手の問題は避けられます。

そしてvarクラスはあくまでも数値を扱うクラスだと思われます。
stringの全機能が何の矛盾もなく使えるでしょうか?そして仮に使えるとしてそれはvarクラスとして意味のあることでしょうか?
public継承では、原則として派生クラスは基底クラスとしてふるまわなくてはなりません。
より具体的にはvarクラスとはstringクラスでなくてはならないのです(チワワは犬です。と同じ意味で)

stringの全機能が必要だとしても、string ポインターへアップキャストできず、実装上必要なだけなら継承は原則的にいらないんです
最後に編集したユーザー GRAM on 2011年11月08日(火) 08:50 [ 編集 1 回目 ]

naohiro19
記事: 256
登録日時: 14年前

Re: varクラスつくったよ!

投稿記事 by naohiro19 » 13年前

CODE:

class foo {
public:
  virtual void bar() = 0;
};
上記のようなインターフェースクラスならpublic継承ですよね

アバター
MoNoQLoREATOR
記事: 284
登録日時: 14年前
住所: 東京

Re: varクラスつくったよ!

投稿記事 by MoNoQLoREATOR » 13年前

v = 200;
v += "100";
cout

using namespace std;

#ifndef _FTOS_
#define _FTOS_
string ftos(double num){
char media[33];
sprintf(media, "%f", num);
string str = media;
return str;
}
#endif

#ifndef _ITOS_
#define _ITOS_
string itos(int val, int radix = 10){
char recep[33];
string output = _itoa(val, recep, radix);
return output;
}
#endif

#ifndef _VAR_
#define _VAR_
class var :protected string{
double mynum;
string outnum;

public:

using string::c_str;
using string::assign;
using string::append;

char forc[101];

double num(){ return mynum; }
string & nums(){
outnum = ftos(mynum);
return outnum;
}
const char * numcc(){
outnum = ftos(mynum);
return outnum.c_str();
}
char * numc(){
strcpy(forc, ftos(mynum).c_str() );
return forc;
}
char * strc(){
strcpy(forc, c_str() );
return forc;
}
void reflect(){ set(forc); }

var & set(int rnum){
mynum = rnum;
assign(itos(rnum) );
return *this;
}
var & operator= (int rnum){ return set(rnum); }

var & set(double rnum){
mynum = rnum;
assign(ftos(rnum) );
return *this;
}
var & operator= (double rnum){ return set(rnum); }

var & set(string &str){
mynum = atof(str.c_str() );
assign(str);
return *this;
}
var & operator= (string &str){ return set(str); }

var & set(const char *str){
mynum = atof(str);
assign(str);
return *this;
}
var & operator= (const char *str){ return set(str); }

var & set(var &media){
mynum = media.num();
assign(media);
return *this;
}

var & add(int rnum){
mynum += rnum;
append(itos(rnum) );
return *this;
}
var & operator+= (int rnum){ return add(rnum); }
var & operator= (double rnum){
if(mynum>=rnum) return true;
return false;
}
bool operator>= (var &media){
if(mynum>=media.num() ) return true;
return false;
}

bool operator (double rnum){
if(mynum>rnum) return true;
return false;
}
bool operator> (var &media){
if(mynum>media.num() ) return true;
return false;
}

bool operator< (double rnum){
if(mynum<rnum) return true;
return false;
}
bool operator< (var &media){
if(mynum<media.num() ) return true;
return false;
}

var(){ mynum=0; }
var(int rnum){ *this = rnum; }
var(double rnum){ *this = rnum; }
var(string &str){ *this = str; }
var(const char *str){ *this = str; }
var(var &media){ *this = media; }
~var(){}
};

var qvar(){
var output;
return output;
}
#endif[/code][/spoil]

それと、qvar()というグローバルな関数を追加しました。
以下のような場面で便利です。

CODE:

int inum = 2525;
printf(qvar()<<"inum="<<inum<<="\n");	//文字列出力。 inum=2525 と表示される
さりげなく <<= を新しくオーバーロードしています。<<を使うとvar&型が返されますが、<<=を使うとconst char*型が返されます。
最後に編集したユーザー MoNoQLoREATOR on 2011年11月08日(火) 23:19 [ 編集 2 回目 ]