Author: wyoung
Date: Wed Jul 2 18:10:12 2008
New Revision: 2301
URL: http://svn.gna.org/viewcvs/mysqlpp?rev=2301&view=rev
Log:
Added userman section describing how to derive from an SSQLS correctly
Modified:
trunk/doc/userman/ssqls.dbx
Modified: trunk/doc/userman/ssqls.dbx
URL:
http://svn.gna.org/viewcvs/mysqlpp/trunk/doc/userman/ssqls.dbx?rev=2301&r1=2300&r2=2301&view=diff
==============================================================================
--- trunk/doc/userman/ssqls.dbx (original)
+++ trunk/doc/userman/ssqls.dbx Wed Jul 2 18:10:12 2008
@@ -615,7 +615,9 @@
<filename>ssqls.pl</filename>. Although it is possible to
change this script to get additional functionality, most of
the time it’s better to just derive a custom class from
- the generated SSQLS to add functionality to it.</para>
+ the generated SSQLS to add functionality to it. (See the <link
+ linkend="ssqls-derivation">next section</link> to see how to do
+ this correctly.)</para>
<para>That said, <filename>ssqls.pl</filename> does have a few
configurables you might want to tweak.</para>
@@ -676,6 +678,120 @@
</sect2>
+ <sect2 id="ssqls-derivation">
+ <title>Deriving from an SSQLS</title>
+
+ <para>Specialized SQL Structures make good base
+ classes. They’re simple, and have few requirements on any
+ class that derives from them. There are some gotchas to look out
+ for, however.</para>
+
+ <para>Consider this:</para>
+
+<programlisting>
+sql_create_2(
+ Base, 1, 2,
+ mysqlpp::sql_varchar, a,
+ mysqlpp::sql_int, b
+);
+
+class Derived : public Base
+{
+public:
+ // constructor
+ Derived(mysqlpp::sql_varchar _a, mysqlpp::sql_int _b) :
+ Base(_a, _b)
+ {
+ }
+
+ // functionality added to the SSQLS through inheritance
+ bool do_something_interesting(int data);
+};</programlisting>
+
+ <para>We’ve derived a class from an SSQLS in order to add
+ a method to it. Easy, right?</para>
+
+ <para>Sadly, too easy. The code has a rather large flaw which makes
+ our derived class unusable as an SSQLS. In C++, if a derived class
+ has a function of the same name as one in the base class, the
+ base class versions of that function are all hidden by those in
+ the derived class. This applies to constructors, too: an SSQLS
+ defines several constructors, but our derived class defines
+ only one, causing that one to hide all of the ones in the base
+ class. Many of the MySQL++ mechanisms that use SSQLSes rely on
+ having these contructors, so our <classname>Derived</classname>
+ above is-not-a <classname>Base</classname>, and so it isn’t
+ an SSQLS. If you try to use <classname>Derived</classname>
+ as an SSQLS, you’ll get compiler errors wherever MySQL++
+ tries to access one of these other constructors.</para>
+
+ <para>There’s another minor flaw, as well. Our lone constructor
+ above takes its parameters by value, but the corresponding
+ constructor in the SSQLS takes them by const reference. Our derived
+ class has technically hidden a fourth base class constructor this
+ way, but this particular case is more a matter of efficiency than
+ correctness. Code that needs the full-creation constructor will
+ still work with our code above, but passing stringish types like
+ <classname>sql_varchar</classname> by value instead of by const
+ reference is inefficient.</para>
+
+ <para>This is the corrected version of the above code:</para>
+
+<programlisting>
+sql_create_2(
+ Base, 1, 2,
+ mysqlpp::sql_varchar, a,
+ mysqlpp::sql_int, b
+);
+
+class Derived : public Base
+{
+public:
+ // default constructor<footnote><para>needed by mechanisms like
<methodname>Query::storein()</methodname>; anything using an STL container,
which usually require default ctors for contained data
structures</para></footnote>
+ Derived() :
+ Base()
+ {
+ }
+
+ // for-comparison constructor<footnote><para>takes the
<parameter>COMPCOUNT</parameter> subset of the SSQLS’s data members, used
for making comparison exemplars, used with
<methodname>Query::update()</methodname> and similar mechanisms; see <xref
linkend="sql_create"/> for more on
<parameter>COMPCOUNT</parameter></para></footnote>
+ Derived(const mysqlpp::sql_varchar& _a) :
+ Base(_a)
+ {
+ }
+
+ // full creation constructor
+ Derived(const mysqlpp::sql_varchar& _a, const mysqlpp::sql_int& _b) :
+ Base(_a, _b)
+ {
+ }
+
+ // population constructor<footnote><para>used in taking raw row data from a
SQL result set and converting it to SSQLS form</para></footnote>
+ Derived(const mysqlpp::Row& row) :
+ Base(row)
+ {
+ }
+
+ // functionality added to the SSQLS through inheritance
+ bool do_something_interesting(int data);
+};</programlisting>
+
+ <para>Now <classname>Derived</classname> is-an SSQLS.</para>
+
+ <para>You might wonder if you can use protected inheritance
+ above to redefine the SSQLS’s public interface. For
+ instance, OO purists might object to the public data members
+ in an SSQLS. You could encapsulate these public data members
+ in the derived class by using protected inheritance, exposing
+ access to the base class’s data members with public
+ accessor methods. The problem with this is that each SSQLS has
+ <emphasis>dozens</emphasis> of public member functions. These are
+ needed by MySQL++ internals, so unless you re-exposed all of them
+ as we did with the constructors above, you’d again have an
+ SSQLS derivative that is-not-an SSQLS. Simply put, only public
+ inheritance is practical with SSQLSes.</para>
+ </sect2>
+
+
<sect2 id="ssqls-blob">
<title>SSQLS and BLOB Columns</title>
_______________________________________________
Mysqlpp-commits mailing list
[email protected]
https://mail.gna.org/listinfo/mysqlpp-commits