- 浏览: 496825 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
jkxydp:
算法运行的结果根本就不对。
BM算法. -
soarwindzhang:
感谢博主的分享,我今天看了您的UFSET非递归的路径压缩时感觉 ...
并查集 -
zhangning290:
楼主好像只考虑了坏字符规则,。没有考虑好后缀
BM算法. -
lsm0622:
文字描述有错误 误导新学者
求有向图的强连通分量(scc):Tarjan算法 -
knightchen:
博主,你太强了!这篇文章对我学习C++多线程很有帮助!谢谢
并发学习之一_windows下ZThread在CodeBlocks上的安装与配置
1,先看个例子:
class Person { ... };
class BankAccount
{
public:
BankAccount(const Person *primaryOwner,
const Person *jointOwner);
virtual ~BankAccount();
virtual void makeDeposit(double amount) = 0;
virtual void makeWithdrawal(double amount) = 0;
virtual double balance() const = 0;
...
};
class SavingsAccount: public BankAccount
{
public:
SavingsAccount(const Person *primaryOwner,
const Person *jointOwner);
~SavingsAccount();
void creditInterest(); // add interest to account
...
};
使用:
list<BankAccount*> allAccounts;
for (list<BankAccount*>::iterator p = allAccounts.begin(); p != allAccounts.end(); ++p)
{
(*p)->creditInterest(); // error!
}
错误:creditInterest在BankAccounts中不存在.
可行的纠正:
for (list<BankAccount*>::iterator p = allAccounts.begin(); p != allAccounts.end(); ++p)
{
static_cast<SavingsAccount*>(*p)->creditInterest(); //downcast
}
注:转型(cast)之于程序员,犹如苹果之于夏娃.
2,如果又有一个新的账户加入.
class CheckingAccount: public BankAccount
{
public:
void creditInterest(); // add interest to account
...
};
我们这时候必须这么做:
for (list<BankAccount*>::iterator p = allAccounts.begin(); p != allAccounts.end(); ++p)
{
if (*p points to a SavingsAccount)
static_cast<SavingsAccount*>(*p)->creditInterest();
else
static_cast<CheckingAccount*>(*p)->creditInterest();
}
根据型别做事,这不是C++的精神,应该使用虚拟函数.
class BankAccount { ... }; // as above
// new class representing accounts that bear interest
class InterestBearingAccount: public BankAccount
{
public:
virtual void creditInterest() = 0; //提供接口
...
};
class SavingsAccount: public InterestBearingAccount
{
... // as above
};
class CheckingAccount: public InterestBearingAccount
{
... // as above
};
如下图所示:
这时候,你可以这么使用:
for (list<BankAccount*>::iterator p = allAccounts.begin(); p != allAccounts.end(); ++p)
{
static_cast<InterestBearingAccount*>(*p)->creditInterest();
}
3,还有另外一种解决的办法:
class BankAccount
{
public:
virtual void creditInterest() {} //基类提供一个什么都不做的缺省实现
...
};
class SavingsAccount: public BankAccount { ... };
class CheckingAccount: public BankAccount { ... };
list<BankAccount*> allAccounts;// look ma, no cast!
for (list<BankAccount*>::iterator p = allAccounts.begin(); p != allAccounts.end(); ++p)
{
(*p)->creditInterest();
}
4,总结:为了摆脱downcast,不论花多少努力都是值得的.
但是偶尔还是无法摆脱downcast.
例如:当我们无权改变BankAccount, SavingsAccount, 或 allAccounts的定义.
这时候,相对于static_cast,还有个比较好的办法:"safe downcasting"(安全向下转型)
使用dynamic_cast,如果失败,会传回null指针.
回到一开始的地方:
class Person { ... };
class BankAccount
{
public:
BankAccount(const Person *primaryOwner,
const Person *jointOwner);
virtual ~BankAccount();
virtual void makeDeposit(double amount) = 0;
virtual void makeWithdrawal(double amount) = 0;
virtual double balance() const = 0;
...
};
class SavingsAccount: public BankAccount
{
public:
void creditInterest(); // add interest to account
...
};
class CheckingAccount: public BankAccount
{
public:
void creditInterest(); // add interest to account
...
};
使用:
list<BankAccount*> allAccounts;
void error(const string& msg);
//至少可以保证downcast失败时,可以侦测到.
for (list<BankAccount*>::iterator p = allAccounts.begin(); p != allAccounts.end(); ++p)
{
if (SavingsAccount *psa = dynamic_cast<SavingsAccount*>(*p))
{
psa->creditInterest();
}
else if (CheckingAccount *pca = dynamic_cast<CheckingAccount*>(*p))
{
pca->creditInterest();
}
// uh oh — unknown account type
else
{
error("Unknown account type!");
}
}
注:downcast必然导致if-then-else风格,比起虚函数,拙劣之极.
万不得已,不要这么使用.
class Person { ... };
class BankAccount
{
public:
BankAccount(const Person *primaryOwner,
const Person *jointOwner);
virtual ~BankAccount();
virtual void makeDeposit(double amount) = 0;
virtual void makeWithdrawal(double amount) = 0;
virtual double balance() const = 0;
...
};
class SavingsAccount: public BankAccount
{
public:
SavingsAccount(const Person *primaryOwner,
const Person *jointOwner);
~SavingsAccount();
void creditInterest(); // add interest to account
...
};
使用:
list<BankAccount*> allAccounts;
for (list<BankAccount*>::iterator p = allAccounts.begin(); p != allAccounts.end(); ++p)
{
(*p)->creditInterest(); // error!
}
错误:creditInterest在BankAccounts中不存在.
可行的纠正:
for (list<BankAccount*>::iterator p = allAccounts.begin(); p != allAccounts.end(); ++p)
{
static_cast<SavingsAccount*>(*p)->creditInterest(); //downcast
}
注:转型(cast)之于程序员,犹如苹果之于夏娃.
2,如果又有一个新的账户加入.
class CheckingAccount: public BankAccount
{
public:
void creditInterest(); // add interest to account
...
};
我们这时候必须这么做:
for (list<BankAccount*>::iterator p = allAccounts.begin(); p != allAccounts.end(); ++p)
{
if (*p points to a SavingsAccount)
static_cast<SavingsAccount*>(*p)->creditInterest();
else
static_cast<CheckingAccount*>(*p)->creditInterest();
}
根据型别做事,这不是C++的精神,应该使用虚拟函数.
class BankAccount { ... }; // as above
// new class representing accounts that bear interest
class InterestBearingAccount: public BankAccount
{
public:
virtual void creditInterest() = 0; //提供接口
...
};
class SavingsAccount: public InterestBearingAccount
{
... // as above
};
class CheckingAccount: public InterestBearingAccount
{
... // as above
};
如下图所示:
这时候,你可以这么使用:
for (list<BankAccount*>::iterator p = allAccounts.begin(); p != allAccounts.end(); ++p)
{
static_cast<InterestBearingAccount*>(*p)->creditInterest();
}
3,还有另外一种解决的办法:
class BankAccount
{
public:
virtual void creditInterest() {} //基类提供一个什么都不做的缺省实现
...
};
class SavingsAccount: public BankAccount { ... };
class CheckingAccount: public BankAccount { ... };
list<BankAccount*> allAccounts;// look ma, no cast!
for (list<BankAccount*>::iterator p = allAccounts.begin(); p != allAccounts.end(); ++p)
{
(*p)->creditInterest();
}
4,总结:为了摆脱downcast,不论花多少努力都是值得的.
但是偶尔还是无法摆脱downcast.
例如:当我们无权改变BankAccount, SavingsAccount, 或 allAccounts的定义.
这时候,相对于static_cast,还有个比较好的办法:"safe downcasting"(安全向下转型)
使用dynamic_cast,如果失败,会传回null指针.
回到一开始的地方:
class Person { ... };
class BankAccount
{
public:
BankAccount(const Person *primaryOwner,
const Person *jointOwner);
virtual ~BankAccount();
virtual void makeDeposit(double amount) = 0;
virtual void makeWithdrawal(double amount) = 0;
virtual double balance() const = 0;
...
};
class SavingsAccount: public BankAccount
{
public:
void creditInterest(); // add interest to account
...
};
class CheckingAccount: public BankAccount
{
public:
void creditInterest(); // add interest to account
...
};
使用:
list<BankAccount*> allAccounts;
void error(const string& msg);
//至少可以保证downcast失败时,可以侦测到.
for (list<BankAccount*>::iterator p = allAccounts.begin(); p != allAccounts.end(); ++p)
{
if (SavingsAccount *psa = dynamic_cast<SavingsAccount*>(*p))
{
psa->creditInterest();
}
else if (CheckingAccount *pca = dynamic_cast<CheckingAccount*>(*p))
{
pca->creditInterest();
}
// uh oh — unknown account type
else
{
error("Unknown account type!");
}
}
注:downcast必然导致if-then-else风格,比起虚函数,拙劣之极.
万不得已,不要这么使用.
发表评论
-
条款43:明智地使用多继承
2010-06-08 09:33 13351,多继承带来的一个根本性的复杂性:模棱两可. 例如: # ... -
条款44:说出你的意思并了解你所说的每一句话
2010-06-08 09:30 7741,彻底了解不同的面向对象架构在C++中的意义. 2,声明一 ... -
条款30:避免写出member function,传回一个non-const function或reference并指向private或protect成员
2010-06-08 09:29 11891,先看一个例子: class Address { ... } ... -
条款4:尽量使用C++风格的注释形式
2010-06-07 09:49 7111,抛弃"/*...*/",改用" ... -
条款2:尽量以<iostream>取代<stdio.h>
2010-06-01 10:36 9721,scanf和printf的缺点:不具有型别安全(type- ... -
条款1:尽量以const和inline取代#define
2010-06-01 10:35 9161,意思就是"尽量以编译器(compiler)&qu ... -
条款42:明智地使用private inheritance(私有继承)
2010-05-29 17:51 9511,先搞清楚private inheritance的行为: ( ... -
条款41:区分inheritance和template
2010-05-29 17:50 6631,首先考虑一个问题: 型别T会影响class的行为吗? 如果 ... -
条款40:通过layering技术来模塑"有一个"(has-a)或"根据某物实现(is-implemented-in-terms-of)"
2010-05-29 17:48 7611,所谓laying,就是以一个class为本,建立另外一个c ... -
条款38:绝对不要重新定义继承而来的缺省参数值
2010-05-29 17:48 7841,首先可以安全的把问题讨论局限于"继承一个带有缺省 ... -
条款37:绝对不要重新定义继承而来的非虚拟函数
2010-05-29 17:47 7261,先看个例子: class B { public: vo ... -
条款36:区分接口继承和实现继承
2010-05-29 17:46 8441,public继承分为两类:接口继承和实现继承. 这两种继承 ... -
条款35:确定你的public继承,模塑出"isa"的关系
2010-05-29 17:46 9531,C++面向对象程序设计最重要的原则: public继承意味 ... -
条款29:避免传回内部数据的handles
2010-05-28 10:35 13461,考虑下面的代码: class string { oper ... -
条款28:尝试切割global namesapce
2010-05-28 10:34 6811,namesapce的使用 namespace std{ ... -
条款50:加强自己对C++的了解
2010-05-25 11:46 8721,只推荐两本书: (1)D&E: The Desig ... -
条款49:尽量让自己熟悉C++标准库
2010-05-25 11:46 7771,标准库的每一样东西几乎都在namespace std中,然 ... -
条款48:不要对编译器的警告视而不见
2010-05-25 11:45 7671,在你忽略一个警告之前,你必须精确了解编译器企图告诉你的是什 ... -
条款47:使用non-local static objects之前先确定它已有初值
2010-05-25 11:45 8271,当一个编译单元内某对象的初始化动作,与另一个编译单元内某对 ... -
条款26:防卫潜伏的ambiguity状态
2010-05-25 11:44 7251, class B; class A { public: ...
相关推荐
downcast-localization:Downcast的本地化字符串
沮丧 用于下载播客的 Python 实用程序 亲爱的小灵魂,你有什么问题吗? 告诉我你为什么这么沮丧。 我已经有很长的运气不好了但我祈祷它终于消失了。 ,保罗西蒙
Type-Safe Downcast(保证安全的向下转型操作) Type-Safe Dynamic Cast(保证安全的动态转型) References并不是Pointers Typeid运算符 7.4 效率有了,弹性呢? 动态共享函数库(Dynamic Shared Libraries) 共享...
Type-Safe Downcast(保证安全的向下转型操作) Type-Safe Dynamic Cast(保证安全的动态转型) References并不是Pointers Typeid运算符 7.4 效率有了,弹性呢? 动态共享函数库(Dynamic Shared Libraries) 共享...
Type-Safe Downcast(保证安全的向下转型操作) Type-Safe Dynamic Cast(保证安全的动态转型) References并不是Pointers Typeid运算符 7.4 效率有了,弹性呢? 动态共享函数库(Dynamic Shared Libraries) 共享...
Python库是一组预先...例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。
Python库是一组预先...例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。
Python库是一组预先...例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。
Python库是一组预先...例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。
Python库是一组预先...例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。
Python库是一组预先...例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。
Python库是一组预先...例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。
Python库是一组预先...例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。
Python库是一组预先...例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。
Encapsulate Downcast 封装向下转型 Replace Error Code with Exception 用异常代替错误码 Replace Exception with Test 用测试代替异常 Chapter 11:Dealing with Generalization 处理泛化关系 ...
Encapsulate Downcast 封装向下转型 Replace Error Code with Exception 用异常代替错误码 Replace Exception with Test 用测试代替异常 Chapter 11:Dealing with Generalization 处理泛化关系 ...
10.13 Encapsulate Downcast(封装「向下转型」动作) 10.14 Replace Error Code with Exception(以异常取代错误码) 10.15 Replace Exception with Test(以测试取代异常) 第11章 处理概括关系 11.1 Pull Up ...
Encapsulate Downcast 封装向下转型 Replace Error Code with Exception 用异常代替错误码 Replace Exception with Test 用测试代替异常 Chapter 11:Dealing with Generalization 处理泛化关系 ...
Encapsulate Downcast 封装向下转型 Replace Error Code with Exception 用异常代替错误码 Replace Exception with Test 用测试代替异常 Chapter 11:Dealing with Generalization 处理泛化关系 ...
Encapsulate Downcast 封装向下转型 Replace Error Code with Exception 用异常代替错误码 Replace Exception with Test 用测试代替异常 Chapter 11:Dealing with Generalization 处理泛化关系 ...