473,320 Members | 1,802 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

questions about dynamic binding

Hello,

I have some questions to do with dynamic binding. The example program
is:

#include<iostream>

using namespace std;

class A{
public:
virtual void f(){cout << "A::f()" << endl;}
};

class B:public A{
public:
void f(){cout << "B::f()" << endl;}
};

int main(){
B b;
A* bp = &b;
// A* bp2 = new B(*bp);
A* bp2 = new A(*bp);
bp2->f();
bp->f();
return 0;
}

As I expected "bp->f()" calls B's f(). However, "bp2->f()" calls A's
f(). Is it because of the "new A", which only copies the A's part of
"*bp" object, or is it because of the behaviour of the synthesized
copy constructor of A? If it is the latter, then can I create a B
object by defining my own copy constructor for A?

In addition, the statement that is commented out produced compiler
error. It says "no matching function for call to 'B::B(A&)'". Can't
compiler find out *bp is in fact a B object?

Thanks,
Jess

May 12 '07 #1
13 1650
// bp points to the object b, even if it is a pointer of class A.
A* bp = &b;

// so the member function B::f should be invoked.
bp->f();

// bp2 points to a object of class A.
A* bp2 = new A(*bp);

// so the member function A::f should be invoked.
bp2->f();

about the statement A* bp2 = new A(*bp);
if class A hasn't any copy constructor, the compiler will use the default
copy constructor to construct a new object.
A::A( const A& a),
because class B derives from class A, so the compiler will use A's part of
the object B to construct the object of class A.

if you write a overload copy constructor for class A, such as
A::A( const B& b),
the compiler will use your custom copy constructor to create the object of
class A.
>>It says "no matching function for call to 'B::B(A&)'". Can't compiler
find out *bp is in fact a B object?
yes, the error is reported at compile time, the dynamic binding is at run
time. so the compiler could not know whether a pointer points to its actual
object at compile time.

"Jess" <wd***@hotmail.com>
??????:11********************@u30g2000hsc.googlegr oups.com...
Hello,

I have some questions to do with dynamic binding. The example program
is:

#include<iostream>

using namespace std;

class A{
public:
virtual void f(){cout << "A::f()" << endl;}
};

class B:public A{
public:
void f(){cout << "B::f()" << endl;}
};

int main(){
B b;
A* bp = &b;
// A* bp2 = new B(*bp);
A* bp2 = new A(*bp);
bp2->f();
bp->f();
return 0;
}

As I expected "bp->f()" calls B's f(). However, "bp2->f()" calls A's
f(). Is it because of the "new A", which only copies the A's part of
"*bp" object, or is it because of the behaviour of the synthesized
copy constructor of A? If it is the latter, then can I create a B
object by defining my own copy constructor for A?

In addition, the statement that is commented out produced compiler
error. It says "no matching function for call to 'B::B(A&)'". Can't
compiler find out *bp is in fact a B object?

Thanks,
Jess

May 12 '07 #2
On May 12, 8:33 pm, "Paolo Maldini" <jifang1...@msn.comwrote:
about the statement A* bp2 = new A(*bp);
if class A hasn't any copy constructor, the compiler will use the default
copy constructor to construct a new object.
A::A( const A& a),
because class B derives from class A, so the compiler will use A's part of
the object B to construct the object of class A.
So, this is the default behaviour of compiler?
if you write a overload copy constructor for class A, such as
A::A( const B& b),
the compiler will use your custom copy constructor to create the object of
class A.
Is there a way that I can overload the copy constructor so that the
object created is in fact of class B?

Thanks,
Jess

May 12 '07 #3
On 2007-05-12 12:13, Jess wrote:
Hello,

I have some questions to do with dynamic binding. The example program
is:

#include<iostream>

using namespace std;

class A{
public:
virtual void f(){cout << "A::f()" << endl;}
};

class B:public A{
public:
void f(){cout << "B::f()" << endl;}
};

int main(){
B b;
A* bp = &b;
// A* bp2 = new B(*bp);
A* bp2 = new A(*bp);
bp2->f();
bp->f();
return 0;
}

As I expected "bp->f()" calls B's f(). However, "bp2->f()" calls A's
f(). Is it because of the "new A", which only copies the A's part of
"*bp" object, or is it because of the behaviour of the synthesized
copy constructor of A?
It's because new A() will create a new object of type A, so when doing
bp2->f() it will call the f() method of the object pointed to by bp2
(which happens to be of type A). When you do bp->f() the type of the
object pointed to is of type B so its f() is called.
If it is the latter, then can I create a B object by defining my own
copy constructor for A?
No, any constructor in an object (regardless if it's a normal
constructor or a copy-constructor) of type T will create an object of
type T, so when you do 'new A()' the type of the object will always be A
(since that is what you specified).
In addition, the statement that is commented out produced compiler
error. It says "no matching function for call to 'B::B(A&)'". Can't
compiler find out *bp is in fact a B object?
No, bp is a pointer to an object of type A, you can either cast the
pointer to a pointer of type B or create a constructor in B which takes
an A as argument.

--
Erik Wikström
May 12 '07 #4
On Sat, 12 May 2007 04:01:58 -0700, Jess wrote:
>if you write a overload copy constructor for class A, such as A::A(
const B& b),
the compiler will use your custom copy constructor to create the object
of class A.

Is there a way that I can overload the copy constructor so that the
object created is in fact of class B?
No a constructor of class A _always_ creates a class A object.

What you are running into seems to be the "virtual constructor" problem.
This is a FAQ. See

http://www.parashift.com/c++-faq-lit....html#faq-20.8

--
Markus Schoder
May 12 '07 #5
On May 12, 12:13 pm, Jess <w...@hotmail.comwrote:
I have some questions to do with dynamic binding. The example program
is:
#include<iostream>
using namespace std;
class A{
public:
virtual void f(){cout << "A::f()" << endl;}

};
class B:public A{
public:
void f(){cout << "B::f()" << endl;}

};
int main(){
B b;
A* bp = &b;
// A* bp2 = new B(*bp);
A* bp2 = new A(*bp);
bp2->f();
bp->f();
return 0;
}
As I expected "bp->f()" calls B's f(). However, "bp2->f()" calls A's
f().
That's because, as written, bp2 points to an A.
Is it because of the "new A", which only copies the A's part of
"*bp" object, or is it because of the behaviour of the synthesized
copy constructor of A? If it is the latter, then can I create a B
object by defining my own copy constructor for A?
It's because in the expression "new A", you tell the compiler
explicitly to create an A object. All of the rest follows;
there is no way that the expression "new A" can create anything
other than an A.

It's a classical case of the compiler doing what you told it
to, and not what you wanted. Otherwise known as "you asked for
it, you got it."
In addition, the statement that is commented out produced compiler
error. It says "no matching function for call to 'B::B(A&)'". Can't
compiler find out *bp is in fact a B object?
No, because it might not be. Virtuality only works on the
object the function is called on. Since no object exists when
the constructor is called, it cannot be virtual, and of course,
virtuality never works on arguments.

The classical solution here is to provide a clone function in
the base class, i.e.:

class A
{
public:
A* clone() const
{
A* result = doClone() ;
assert( typeid( *result ) == typeid( *this ) ) ;
return result ;
}

private:
virtual A* doClone() const
// Except that usually, this will be pure virtual.
// It's fairly rare to have virtual functions in a
// base class which aren't pure virtual.
{
return new A( *this ) ;
}
} ;

class B
{
private:
virtual A* doClone() const
{
return new B( *this ) ;
}
} ;

When you want to copy, you use clone, rather than new. (I've
also occasionally found it useful to have a function "another",
along the same lines as clone(), but using default construction
rather than copy.)

--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

May 12 '07 #6
On May 12, 11:03 pm, James Kanze <james.ka...@gmail.comwrote:
On May 12, 12:13 pm, Jess <w...@hotmail.comwrote:
....
The classical solution here is to provide a clone function in
the base class, i.e.:

class A
{
public:
A* clone() const
{
A* result = doClone() ;
assert( typeid( *result ) == typeid( *this ) ) ;
return result ;
}

private:
virtual A* doClone() const
// Except that usually, this will be pure virtual.
// It's fairly rare to have virtual functions in a
// base class which aren't pure virtual.
{
return new A( *this ) ;
}
} ;

class B
{
private:
virtual A* doClone() const
{
return new B( *this ) ;
}
If it was not a private method, it may be useful to define clone
methods to return the actual type they create. The compiler handles
upcasting for you if it is called from a base class. This is called a
co-variant return.

virtual B* doClone() const
{
return new B( *this ) ;
}

May 12 '07 #7
Gianni Mariani wrote:
On May 12, 11:03 pm, James Kanze <james.ka...@gmail.comwrote:
On May 12, 12:13 pm, Jess <w...@hotmail.comwrote:
...
The classical solution here is to provide a clone function in
the base class, i.e.:
class A
{
public:
A* clone() const
{
A* result = doClone() ;
assert( typeid( *result ) == typeid( *this ) ) ;
return result ;
}
private:
virtual A* doClone() const
// Except that usually, this will be pure virtual.
// It's fairly rare to have virtual functions in a
// base class which aren't pure virtual.
{
return new A( *this ) ;
}
} ;
class B
{
private:
virtual A* doClone() const
{
return new B( *this ) ;
}
If it was not a private method, it may be useful to define clone
methods to return the actual type they create. The compiler handles
upcasting for you if it is called from a base class. This is called a
co-variant return.
virtual B* doClone() const
{
return new B( *this ) ;
}
I know that the possibility exists, but I have my doubts with
regards to the utility. If for some reason, the interface
specification of B includes this extension, it is relatively
easy to add another public function along the lines of that in
A. With, of course, the same post-condition.

(In practice, I'm not sure just how important the verification
of the post condition is in this case. In the vast majority of
the cases, the virtual clone function can---and in fact
must---be pure in the base class, and there is only one level of
inheritance, so the compiler will not allow you to instantiate a
class which forgets it. And even in the other cases, it's the
sort of thing that tends to be spotted immediately in code
review. But the technique of using a non-virtual public
function to verify pre- and post-conditions and invariants is
generally useful, and worth knowing and practicing.)

--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

May 12 '07 #8
On May 12, 11:03 pm, James Kanze <james.ka...@gmail.comwrote:
Many thanks. Regarding your example:
class A
{
public:
A* clone() const
{
A* result = doClone() ;
assert( typeid( *result ) == typeid( *this ) ) ;
return result ;
}
Why do you need to check typeid? "clone" isn't virtual, then will the
correct version be called if I try to "clone" a B object? Is it true
that if a non-virtual function (here "clone") calls a virtual function
(doClone),then the caller function is automatically virtual?
private:
virtual A* doClone() const
// Except that usually, this will be pure virtual.
// It's fairly rare to have virtual functions in a
// base class which aren't pure virtual.
{
return new A( *this ) ;
}
} ;
Why is it necessary to have another virtual function here that is also
private? What if I put this line of code into "clone()"?
class B
{
private:
virtual A* doClone() const
{
return new B( *this ) ;
}
} ;
If I have a B object "b", then if I do "b.clone()", then "A"'s clone()
method will be called, is it right? I guess what happens next is that
A's clone() calls "doClone()", since this is virtual, then B's
doClone" is called.

I'm still not sure why doClone is needed. Would it work if I do:

class A
{
public:
virtual A* clone() const
{
A* result = new A(*this) ;
assert( typeid( *result ) == typeid( *this ) ) ;
return result ;
}
};

class B
{
B* clone() const
{
return new B( *this ) ;
}
} ;

Thanks,
Jess

May 13 '07 #9
On May 12, 11:37 pm, Gianni Mariani <gi3nos...@mariani.wswrote:
If it was not a private method, it may be useful to define clone
methods to return the actual type they create. The compiler handles
upcasting for you if it is called from a base class. This is called a
co-variant return.

virtual B* doClone() const
{
return new B( *this ) ;
}
Thanks for pointing out the co-variant return type. Does it make no
difference if the return is A* or B*?

Jess

May 13 '07 #10
On May 13, 2:52 pm, Jess <w...@hotmail.comwrote:
On May 12, 11:03 pm, James Kanze <james.ka...@gmail.comwrote:
Many thanks. Regarding your example:
class A
{
public:
A* clone() const
{
A* result = doClone() ;
assert( typeid( *result ) == typeid( *this ) ) ;
return result ;
}
Why do you need to check typeid?
To catch post-condition violations.
"clone" isn't virtual, then will the
correct version be called if I try to "clone" a B object?
"clone" isn't virtual, because the only correct version is in
the base class. "clone" calls a virtual function, "doClone" to
do the actual work.

This is the usual C++ implementation of programming by contract.
Is it true that if a non-virtual function (here "clone") calls
a virtual function (doClone),then the caller function is
automatically virtual?
No. The whole point of the exercise is that it is impossible to
call the virtual function without the post-condition checks.
private:
virtual A* doClone() const
// Except that usually, this will be pure virtual.
// It's fairly rare to have virtual functions in a
// base class which aren't pure virtual.
{
return new A( *this ) ;
}
} ;
Why is it necessary to have another virtual function here that is also
private? What if I put this line of code into "clone()"?
It won't work, because clone() isn't virtual.
class B
{
private:
virtual A* doClone() const
{
return new B( *this ) ;
}
} ;
If I have a B object "b", then if I do "b.clone()", then "A"'s clone()
method will be called, is it right? I guess what happens next is that
A's clone() calls "doClone()", since this is virtual, then B's
doClone" is called.
Right. A defines a contract. In this case, we've done nothing
in B to define a new contract, so A's contract still holds.
Which means that we start by calling a function in A, in order
to enforce the contract.

In practice, this is the usual situation. I'd guess that in
something like 90% of the cases involving inheritance, you
define a contract in a base class, and inherit, one level deep,
to provide different implementations. Practically, the only
time the user sees the derived class is when he constructs one;
all other accesses are through the base class.

There are cases, however, where the derived class wants to
provide an extended contract. Thus, for example, B might decide
to offer an extended guarantee for clone()---not just an A*, but
a B*. (Clone is actually a pretty poor example for this, since
the post-condition in A says that the pointer returned by
B::clone will point to a B. But the principle applies in
general.) In such cases, B is free to provide a new non-virtual
public function, which validates the new contract. Users who
know they have a B, and want to use the extended contract,
dynamic_cast their pointer to B*, and use it.
I'm still not sure why doClone is needed. Would it work if I do:
class A
{
public:
virtual A* clone() const
{
A* result = new A(*this) ;
assert( typeid( *result ) == typeid( *this ) ) ;
return result ;
}
};
class B
{
B* clone() const
{
return new B( *this ) ;
}
} ;
It would work, but what's the point. What happens if you
derived C from B, and forget to override clone. Everything
compiles fine, but anytime you clone a C, you actually get a B.
Your post condition is violated, and you never notice it.
(Actually, of course, you will notice it further down the road.
When you end up trying to understand why you have a B, when you
should have a C.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

May 14 '07 #11
On May 14, 5:39 pm, James Kanze <james.ka...@gmail.comwrote:
On May 13, 2:52 pm, Jess <w...@hotmail.comwrote:
On May 12, 11:03 pm, James Kanze <james.ka...@gmail.comwrote:
Many thanks. Regarding your example:
class A
{
public:
A* clone() const
{
A* result = doClone() ;
assert( typeid( *result ) == typeid( *this ) ) ;
return result ;
}
Why do you need to check typeid?

To catch post-condition violations.
"clone" isn't virtual, then will the
correct version be called if I try to "clone" a B object?

"clone" isn't virtual, because the only correct version is in
the base class. "clone" calls a virtual function, "doClone" to
do the actual work.

This is the usual C++ implementation of programming by contract.
Is it true that if a non-virtual function (here "clone") calls
a virtual function (doClone),then the caller function is
automatically virtual?

No. The whole point of the exercise is that it is impossible to
call the virtual function without the post-condition checks.
private:
virtual A* doClone() const
// Except that usually, this will be pure virtual.
// It's fairly rare to have virtual functions in a
// base class which aren't pure virtual.
{
return new A( *this ) ;
}
} ;
Why is it necessary to have another virtual function here that is also
private? What if I put this line of code into "clone()"?

It won't work, because clone() isn't virtual.
class B
{
private:
virtual A* doClone() const
{
return new B( *this ) ;
}
} ;
If I have a B object "b", then if I do "b.clone()", then "A"'s clone()
method will be called, is it right? I guess what happens next is that
A's clone() calls "doClone()", since this is virtual, then B's
doClone" is called.

Right. A defines a contract. In this case, we've done nothing
in B to define a new contract, so A's contract still holds.
Which means that we start by calling a function in A, in order
to enforce the contract.

In practice, this is the usual situation. I'd guess that in
something like 90% of the cases involving inheritance, you
define a contract in a base class, and inherit, one level deep,
to provide different implementations. Practically, the only
time the user sees the derived class is when he constructs one;
all other accesses are through the base class.

There are cases, however, where the derived class wants to
provide an extended contract. Thus, for example, B might decide
to offer an extended guarantee for clone()---not just an A*, but
a B*. (Clone is actually a pretty poor example for this, since
the post-condition in A says that the pointer returned by
B::clone will point to a B. But the principle applies in
general.) In such cases, B is free to provide a new non-virtual
public function, which validates the new contract. Users who
know they have a B, and want to use the extended contract,
dynamic_cast their pointer to B*, and use it.
I'm still not sure why doClone is needed. Would it work if I do:
class A
{
public:
virtual A* clone() const
{
A* result = new A(*this) ;
assert( typeid( *result ) == typeid( *this ) ) ;
return result ;
}
};
class B
{
B* clone() const
{
return new B( *this ) ;
}
} ;

It would work, but what's the point. What happens if you
derived C from B, and forget to override clone. Everything
compiles fine, but anytime you clone a C, you actually get a B.
Your post condition is violated, and you never notice it.
(Actually, of course, you will notice it further down the road.
When you end up trying to understand why you have a B, when you
should have a C.)

--
James Kanze (GABI Software) email:james.ka...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Thanks a lot for the explanations! I think there are situations where
virtual functions don't help. For example, I may have a function "f"
that takes a pointer of type A*, and it needs to know if the pointed
object is really A or B before doing anything. Suppose I don't have
access to A and B's implementations, and so I can't define any new
virtual functions. In this case, how can the function "f" know if
it's got an A object or B object?

Thanks,
Jess

May 14 '07 #12
On May 14, 1:46 pm, Jess <w...@hotmail.comwrote:
On May 14, 5:39 pm, James Kanze <james.ka...@gmail.comwrote:
Thanks a lot for the explanations! I think there are situations where
virtual functions don't help. For example, I may have a function "f"
that takes a pointer of type A*, and it needs to know if the pointed
object is really A or B before doing anything. Suppose I don't have
access to A and B's implementations, and so I can't define any new
virtual functions. In this case, how can the function "f" know if
it's got an A object or B object?
You can always try a dynamic_cast:

void
f( A* pA )
{
B* pB = dynamic_cast< B* >( pA ) ;
if ( pB != NULL ) {
// It's really a B...
} else {
// It's not a B ...
}
}

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

May 15 '07 #13
On May 15, 5:33 pm, James Kanze <james.ka...@gmail.comwrote:
On May 14, 1:46 pm, Jess <w...@hotmail.comwrote:
On May 14, 5:39 pm, James Kanze <james.ka...@gmail.comwrote:
Thanks a lot for the explanations! I think there are situations where
virtual functions don't help. For example, I may have a function "f"
that takes a pointer of type A*, and it needs to know if the pointed
object is really A or B before doing anything. Suppose I don't have
access to A and B's implementations, and so I can't define any new
virtual functions. In this case, how can the function "f" know if
it's got an A object or B object?

You can always try a dynamic_cast:

void
f( A* pA )
{
B* pB = dynamic_cast< B* >( pA ) ;
if ( pB != NULL ) {
// It's really a B...
} else {
// It's not a B ...
}
}

--
James Kanze (GABI Software) email:james.ka...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

I see, great to know that, thanks!
Jess

May 15 '07 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: festiv | last post by:
Hi there, I want to learn how the compiler is implementing the dynamic binding. where can i read about this subject (the hole process). thanks.
3
by: prashna | last post by:
Hi all, Is'nt a function invocation through a function pointer is dynamic binding? For example consider the following program 1 int main() 2 { 3 int (*fun_ptr)(); 4 int...
9
by: Gibby Koldenhof | last post by:
Hiya, Terrible subject but I haven't got a better term at the moment. I've been building up my own library of functionality (all nice conforming ISO C) for over 6 years and decided to adopt a...
3
by: compgeek.320 | last post by:
Hi Everyone, Can any one explain me about Dynamic binding related to OOPs concepts.I studied in a book that the polymorphic fuction call will be decided in the runtime rather than the compile...
25
by: Syam | last post by:
Fully answered interview questions in c and c++ from http://www.faiqs.com
14
by: shamirza | last post by:
Question Do ActiveX DLLs made in VB still need the VB runtimes on the machine? ________________________________________ Answer In a word, Yes. Visual Basic does not support what is known...
2
by: 09876 | last post by:
Hi: all I understand the difference between dynamic binding and static binding. But I just wonder what is the point to make the distinction between the dynamic binding and static binding. For...
8
by: wangdaixing | last post by:
I am reading "Programming .NET Components" 2nd Edition by Juval Lowy, O'Reilly. In Appendix E, there is a chapter "Coding Practices" which I agree and practice mostly. However, there are a few...
26
by: Aaron \Castironpi\ Brady | last post by:
Hello all, To me, this is a somewhat unintuitive behavior. I want to discuss the parts of it I don't understand. .... f= lambda: n .... 9 9
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.